索引和查询优化
 
为什么要索引?
想想我们上小学的时候是怎么查字典的,比方查 理想的 “理”,首先在索引里找到声母 “l”,再找到 “li”
找到 “li”所在的页数,
 
我们之前建的所有mysql 表都是没有索引的,找数据就要全表扫描,想象如果字典里的字都是乱序的,我们
要找一个字的话可能需要翻遍整个字典,
 
同样在msyql 中也有索引,mysql 中的索引有四种:主键,唯一索引,全文索引,普通索引
 
主键
 
主键是不可重复,且不能包含null 的索引
创建主键的方式:
法儿一:
create table pk_test(id int,primary key(id));
法儿二:
alter table test add primary key(f1);
 
主键不可重复指的是主键的组合不重复即可,组成主键的单个字段可能是重复的,例如
MariaDB [jason]> show create table pk_test;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                                                                               |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| pk_test | CREATE TABLE `pk_test` (
  `f1` int(11) NOT NULL,
  `f2` int(11) NOT NULL,
  `f3` char(10) DEFAULT NULL,
  PRIMARY KEY (`f1`,`f2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into pk_test (f1,f2) values(1,1),(1,2);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
 
MariaDB [jason]> select * from pk_test;
+----+----+------+
| f1 | f2 | f3   |
+----+----+------+
|  1 |  1 | NULL |
|  1 |  2 | NULL |
+----+----+------+
2 rows in set (0.00 sec)
 
 
普通索引
 
普通索引是可以重复的
创建方式如下:
法儿一:
create table index_test(id int,name char(5),index(name));
法儿二:
alter table index_test add index(id);
 
我们来看下建表语句
MariaDB [jason]> show create table index_test \G;
*************************** 1. row ***************************
       Table: index_test
Create Table: CREATE TABLE `index_test` (
  `id` int(11) DEFAULT NULL,
  `name` char(5) DEFAULT NULL,
  KEY `name` (`name`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.01 sec)
 
怎么就冒出来个 “KEY”,KEY 就是我们刚才建的index ,key 和index 是同义词,不过我一般习惯用index
 
全文索引
 
全文索引是对表中的大文本进行索引的,包括 char,varchar,text,关于全文索引的一些介绍可以看
 
创建全文索引的方法如下
法儿一:
MariaDB [jason]> create table ft_test(f1 char(200),f2 varchar(200),f3 text,f4 int,fulltext(f1));
法儿二:
alter table ft_test add fulltext(f2,f3);
 
现在我们往表里插入两条数据玩玩儿
insert into ft_test(f1,f2,f3) values
('Brian and his two friends are hanging','out at a bar','They are talking about life'),
('sports and other','guy things when the conversation','finally gets around to to their marriages'),
('His first friend says','You know what','under the bed and it was not mine');
 
看看fulltext 的使用方法
 
MariaDB [jason]> select f1 from ft_test where match(f1) against('two');
+---------------------------------------+
| f1                                    |
+---------------------------------------+
| Brian and his two friends are hanging |
+---------------------------------------+
 
我们来看看match against 是个啥玩意儿
MariaDB [jason]> select f1 ,match(f1) against('two') as aa from ft_test;
+---------------------------------------+---------------------+
| f1                                    | aa                  |
+---------------------------------------+---------------------+
| Brian and his two friends are hanging | 0.22764469683170319 |
| sports and other                      |                   0 |
| His first friend says                 |                   0 |
+---------------------------------------+---------------------+
他是一个关联系数,where 条件只过滤系数大于0的记录
 
 噪声单词
 
尝试下面的语句
 
MariaDB [jason]> select f1 from ft_test where match(f1) against('are');
Empty set (0.00 sec)
有什么异样?are 明明在f1 中是存在的,但是结果却是empty,innodb 维持了一个stopword 表,stopword
默认是不被索引的,所以用are 做索引会被忽略
 
唯一索引
 
唯一索引与普通索引类似,区别是唯一索引不可以重复
创建唯一索引的方法
法儿一:
create table uq_test(f1 char(20),f2 char(20),f3 int,unique(f1));
法儿二:
alter table uq_test add unique(f2);
 
 
部分索引
 
对于char,varchar,blob,text 等字符串类型的值,其存储的内容可能很长,如果对整个字段做索引
则索引回很大,且效率很低,这时可以采用部分索引,也叫前缀索引,看例子
 
建表
create table part_index(city char(10));
插入数据
insert into part_index values('hebei'),('beijing'),('tianjin'),('henan'),('anhui');
 
到底选择前缀的几个字符效果最佳呢?可以采用下面的方法计算
MariaDB [jason]> select count(distinct(left(city,1)))/count(*) as c1,
    -> count(distinct(left(city,2)))/count(*) as c2,
    -> count(distinct(left(city,3)))/count(*) as c3,
    -> count(distinct(left(city,4)))/count(*) as c4,
    -> count(distinct(left(city,5)))/count(*) as c5,
    -> count(distinct(city))/count(*) as c6
    -> from part_index;
+--------+--------+--------+--------+--------+--------+
| c1     | c2     | c3     | c4     | c5     | c6     |
+--------+--------+--------+--------+--------+--------+
| 0.8000 | 0.8000 | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
+--------+--------+--------+--------+--------+--------+
 
 
可以看到当选用前3个字符的时候就和使用全部字符比例相当了,所以可以选用前3个字符做前缀索引。
 
那么我们来给上面的表添加前缀索引 
alter table part_index add index(city(3))
 
 
 
 
 
 

《一起学mysql》3的更多相关文章

  1. 百度实习生,以修仙者的角度聊聊怎么学MySQL,不来看看你的修为如何吗?

    目录 因为我个人比较喜欢看修仙类的小说,所以本文的主体部分借用修仙者的修为等级,将学习旅程划分成:练气.筑基.结丹.元婴.化神.飞升六个段位,你可以看下你大概在哪个段位上哦! 本文目录: 我为什么要写 ...

  2. 自导自演的面试现场,趣学MySQL的10种文件

    导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 24 篇. 今天我要跟你分享的MySQL话题是:"自导自演的数据库面试现场--谈谈MySQL的10种文件" 换一种写作风格 ...

  3. DF学Mysql(二)——数据表的基本操作

    1.创建数据表 先使用“USE <数据库名>”指定在哪个数据库中操作 CREATE TABLE <表名> ( 字段1 数据类型 [列级别约束条件] [默认值], 字段2 数据类 ...

  4. 从零开始学MySQL(二)

    鉴于上节篇幅以安装为主,因此对于调用mysql所需要使用的“命令”只是略微提及.随之而来就会带给读者诸多不解了,因为你会思考,这串长长的字符到底有什么特殊的含义呢?聪明的你可能早就抱着好奇心去“摆渡” ...

  5. 从零开始学MySQL(四)

    上节连接:https://www.cnblogs.com/RajXie/p/10880809.html 上节说到,在创建表的同时,需要给出列的定义.列的定义可展开如下: 列名 列的数据类型 列的一些其 ...

  6. Java必学MySQL数据库应用场景

    Java教程分享Java必学之MySQL数据库应用场景,在当前的后台开发中,MySQL应用非常普遍,企业在选拔Java人才时也会考察求职者诸如性能优化.高可用性.备份.集群.负载均衡.读写分离等问题. ...

  7. DF学Mysql(三)——Mysql数据类型

    Mysql数据类型分为:整数类型.浮点数类型.定点数类型日期与时间类型字符串类型二进制类型 整数类型 字节数 无符号数取值范围 有符号数取值范围TINYINT 1 0-255 -128-127SMAL ...

  8. DF学Mysql(三)——索引操作

    概要: 数据库对象索引其实与书的目录非常相似,主要是为了提高从表中检索数据的速度. 由于数据存储在数据库表中,所以索引是创建在数据库表对象上的,由表中的一个字段或多个字段生成的键组成,这些键存储在数据 ...

  9. 这半年时间学Mysql的总结

    一条sql语句的执行流程 select * from t where id=1 1.mysql执行一条查询语句的流程 1.1客户端输入用户名密码连接mysql服务器 1.2查询这条sql语句有没有对应 ...

  10. 《一起学mysql》4

    索引的使用   索引太少返回结果很慢,但是索引太多,又会占用空间.每次插入新记录时,索引都会针对变化重新排序   什么时候使用索引 1.where 从句中用到的字段  select * from tb ...

随机推荐

  1. Anaconda安装第三方库与pip和conda 添加国内源

    Anaconda安装第三方库 PIP使用命令 Anaconda命令 pip和conda 添加国内源 1:PIP相关命令 卸载 pip uninstall XXX 1.升级pip python -m p ...

  2. CentOS 7 firewalld详解,添加删除策略

    一.CentOS7中firewall防火墙 修改防火墙配置文件之前,需要对之前防火墙[/etc/firewalld/zones/public.xml]做好备份 重启防火墙后,需要确认防火墙状态和防火墙 ...

  3. HTML5 Canvas 为网页添加文字水印

    <!DOCTYPE html> <html> <body> <canvas id=" style="border:1px solid #d ...

  4. SynchronusQueue

    /** * 当向SynchronousQueue插入元素时,必须同时有个线程往外取 * SynchronousQueue是没有容量的,这是与其他的阻塞队列不同的地方 */ public class S ...

  5. python爬取小说

    运行结果: 代码: import requests from bs4 import BeautifulSoup from selenium import webdriver import os cla ...

  6. python基础(33):线程(一)

    1. 线程概念的引入背景 1.1 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在 ...

  7. mysql - 锁及事务的认识

    mysql事务特性:一致性原子性隔离性持久性 //mysql 事务隔离级别 读未提交 读未提交的数据 读已提交 读已提交的数据 串行序列化 一个事务完成了再执行另一个事务 可重复读(数据库默认) 就算 ...

  8. 多线程学习二:线程池 ExecutorService

    创建线程池的2种方式: 使用线程池方式1--Runnable接口: 通常,线程池都是通过线程池工厂创建,再调用线程池中的方法获取线程,再通过线程去执行任务方法. Executors:线程池创建工厂类: ...

  9. crm-2

    1.分页 web必备的功能 1)批量制造测试数据 定义一个空列表用于存储 orm对象 ,models.表名(字段=...)创建orm对象append到列表 ,使用bulk_create(对象列表)一次 ...

  10. Java 日期处理类

    日期处理类 Date类 当前日期时间 java.util.Date import java.util.Date; public class TestDemo { public static void ...