那位先生

个人站

前世五百次回眸,才能换得今生的一次擦肩而过。


MySQL-03-创建高性能的索引

1.索引基础

1.概述

索引:是存储引擎用户快速找到记录的一种数据结构。
工作原理:现在索引中找到对应的值,然后根据匹配的索引记录找到对应的数据行。select *from student where id = 5;先在索引上按id=5查找,然后返回包含该值的数据行。

2.索引的类型

在MySQL中索引是在存储引擎层而不是在服务层实现的。不同的存储引擎的索引工作方式不一样。常见的有B-Tree、哈希索引、空间数据索引(R-Tree)、全文索引。

3.索引的优点

索引可以让服务器快速定位到表的指定位置。1.大大减少了服务器需要扫描的数量。2.索引可以帮助服务器避免排序和临时表。3.索引可以将随机IO变为顺序IO。
索引并不总是最好的工具。对于非常小的表,大部分情况下全表扫描更高效。对于中到大型的表,索引就非常有效。对于特大型的表,建立和使用索引的代价随之增加,可能需要分区。

4.高性能的索引策略

独立的列:如果查询中的列不是独立的(不能是表达式的一部分,比如:where id+1=5),则MySQL就不会使用索引。
索引的选择性:不重复的值和数据表的记录总数的比值,范围从 1/#t 到 1 之间。索引的选择性越高则查询效率越高(不重复值尽量多),这样可以让MySQL在查询的时候过滤掉更多的行,唯一索引的选择性是1,这样是最好的索引选择性。
前缀索引:对于BLOB、TEXT或者很长的VARCHAR,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度。原则前缀的基数应该接近完整列的基数。计算前缀长度的选择性:

select count(distinct left(name,3))/count(*) as sel3,
	count(distinct left(name,4))/count(*) as sel4,
	count(distinct left(name,5))/count(*) as sel5
	from student;

当多个结果接近时,则取该长度。添加前缀索引alter table add key(name(4));。注意:MySQL无法使用前缀索引进行order by 和group by.
多列的索引:当服务器对多个索引做相交操作时(通常有多个and)或者联合操作(通常多个or)。
选择合适的索引列顺序:在B-TREE中,索引列的顺序意味着索引首先按照最左列进行排序,其次是第二列,等等。选择经验:一般将选择性最高的列放在索引最前列。
聚簇索引:略。
覆盖索引:一个索引包含所有需要查询的字段。MySQL可以直接使用索引来直接获取列的数据,这样就不需要读取数据行。MySQL可以在索引中做最左前缀匹配的like操作,但如果like以通配符开始会失效,解决办法是使用延迟关联。例如: select *from student s join (select id from student where name like '%xie%') as a on (a.id = s.id);查询的第一阶段(join的子查询)可以使用覆盖索引,先找到匹配的id,然后根据id在外层查询获取需要的所有列。
使用索引扫描来排序:如果explain 出来的type 列的值为’idex’则说明mysql使用了索引扫描来排序。如果索引不能覆盖查询所需的全部列,那就不得不扫描每一条索引记录都回标查询对应的行,特别慢。mysql可以使用同一列索引既满足排序 又用户查找行,因此,如果可能尽量覆盖两种。只有当索引的列的顺序和order by字句的顺序完全一致时,并且所有列的排序方向一致(默认 asc)时,MySQL才能使用索引来对结果做排序。举例:

CREATE TABLE tb_test_index( 
  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,  
   `age` INT(11) DEFAULT NULL,   
   `birth` timestamp not NULL 
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
alter table tb_test_index add index idx_age_bir(age,birth);
explain select *from tb_test_index where 1=1 order by age,birth;	Using index;

explain select *from tb_test_index where 1=1 order by age;	Using index;

explain select *from tb_test_index where 1=1 order by birth;	Using index; Using filesort;

explain select *from tb_test_index where age = 10 order by birth;	Using where; Using index;

explain select *from tb_test_index where age > 10 order by birth;	Using where; Using index; Using filesort

explain select *from tb_test_index where age >10 order by age;	Using where; Using index

explain select *from tb_test_index where birth >10 order by age;	Using where; Using index

explain select *from tb_test_index where age >10 order by age,birth;	Using where; Using index

explain select *from tb_test_index where age >10 order by age asc,birth;	Using where; Using index

explain select *from tb_test_index where age >10 order by age asc,birth desc;	Using where; Using index; Using filesort

explain select *from tb_test_index where age >10 order by age desc,birth;	Using where; Using index; Using filesort

explain select *from tb_test_index where age >10 order by age desc,birth desc;	Using where; Using index

5.日期和时间类型

MySQL提供了两种相似的日期类型:DATETIME和TIMESTAMP。MySQL能存储的最小粒度为秒。
DATETIME:能保存最大范围的值为:1001年~9999年,精度为秒。它把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,与时区无关,使用8个字节的存储空间。 TIMESTAMP:保存了从1970年1月1日午夜(格林尼治时间)以来的秒数,它和UNIX时间戳相同,使用4个字节的存储空间。因为它的范围比DATETIME小:1970年~2038年。
TIMESTAMP提供的值和时区有关,而DATETIME则保留文本表示的日期和时间。除特殊情况外,通常尽量使用TIMESTAMP,因为相比DATETIME更节省空间。

6.选择标识符(identitier)

要跟关联表对应的列类型要一样,而且要精确匹配,包括像UNSIGNED这样的属性。保证未来增长空间的前提下,应该选择最小的数据类型。最好选择整数类型,因为快,而且可以使用AUTO_INCREMENT。不要使用ENUM和SET类型。 尽量避免使用字符串,因为耗空间。UUID不如递增的整数好用。

2.MySQL schema设计中的缺陷

避免使用太多的列;避免使用太多的关联(最好12以内);避免过度使用枚举或者SET。

3.范式和反范式化

1.范式的优点和缺点

优点:更新操作比反范式化要快;很少或没有重复列,所以修改的数据会更少;范式化的表小,可以更好的放在内存,所以执行操作会更快;很少多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句。
缺点:通常需要关联。

2.反范式的优点和缺点

优点:很好的避免关联。

3.混用范式化和反范式化

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
你说多少就多少

比五毛钱特效专业哦