当前位置: 首页 > 科技观察

如何理解和正确使用MySQL索引

时间:2023-03-19 13:44:41 科技观察

1.概述索引是存储引擎用来快速查找记录的一种数据结构。合理使用数据库索引可以大大提高系统的访问性能。接下来主要介绍MySql数据库中Index的种类,以及如何创建更合理高效的索引技巧。注:这里主要针对InnoDB存储引擎的B+Tree索引数据结构2.索引的优点2.1。大大减少了服务器需要扫描的数据量,从而提高了数据检索的速度2.2.帮助服务器避免排序和临时表2.3。可以将随机I/O变为顺序I/O3。索引创建3.1。主键索引ALTERTABLE'table_name'ADDPRIMARYKEY'index_name'('column');column');3.3、普通索引ALTERTABLE'table_name'ADDINDEX'index_name'('column');3.4、全文索引ALTERTABLE'table_name'ADDFULLTEXT'index_name'('column');3.5、复合索引ALTERTABLE'table_name'ADDINDEX'index_name'('column1','column2',...);4.B+Tree索引规则创建测试用户表DROPTABLEIFEXISTSuser_test;CREATETABLEuser_test(idintAUTO_INCREMENTPRIMARYKEY,user_namevarchar(30)NOTNULL,sexbit(1)NOTNULLDEFAULTb'1',cityvarchar(50)NOTNULL,ageintNOTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8;创建一个组合索引:ALTERTABLEuser_testADDINDEXidx_user(user_name,city,age);它是指匹配索引中的所有列。以上面创建的索引为例,在where条件之后,可以同时查询以(user_name,city,age)为条件的数据。注意:与where后面查询条件的先后顺序无关。这里是很多同学容易误会的地方。SELECT*FROMuser_testWHEREuser_name='feinik'ANDage=26ANDcity='广州';匹配最左边的索引列,如:上面创建的索引可用于查询条件:(user_name),(user_name,city),(user_name,city,age)注意:满足最左边前缀查询条件的顺序和索引列的顺序不相关,如:(city,user_name),(age,city,user_name)4.1.3、匹配列前缀是指匹配列值的开头,如:查询用户名以feinik开头的所有用户SELECT*FROMuser_testWHEREuser_nameLIKE'feinik%';4.1.4.匹配范围值如:查询所有用户名以feinik开头的用户,这里使用索引的第一列SELECT*FROMuser_testWHEREuser_nameLIKE'feinik%';4.2、索引限制(1)、where查询条件不包括索引列中最左边的索引列,则不能使用索引查询,如:SELECT*FROMuser_testWHEREcity='Guangzhou';或SELECT*FROMuser_testWHEREage=26;或SELECT*FROMuser_testWHEREcity='广州'ANDage='26';(2)、即使where查询条件是最左边的索引列,也不能使用索引查询用户名以feinikSELECT*FROMuser_testWHEREuser_namelike'%feinik'结尾的用户;(3)、如果where查询条件中存在某列的范围查询,则右边的所有列都不能使用索引优化查询,如:SELECT*FROMuser_testWHEREuser_name='feinik'ANDcityLIKE'Guangzhou%'ANDage=26;5.高效的索引策略5.1.索引列不能是表达式的一部分,也不能作为函数的参数,否则不能使用索引查询。SELECT*FROMuser_testWHEREuser_name=concat(user_name,'fei');5.2.前缀索引有时需要索引很长的字符列,这会增加索引的存储空间,降低索引的效率。一种策略是使用散列索引。另一种选择是使用前缀索引,它选择字符列的前n个字符作为索引,可以大大节省索引空间,提高索引效率。5.2.1前缀索引的选择性前缀索引要选择足够长的前缀以保证高选择性,同时又不能太长,我们可以通过以下方式计算出合适的前缀索引选择长度值:(1)SELECTCOUNT(DISTINCTindex_column)/COUNT(*)FROMtable_name;--index_column表示要添加前缀索引的列注意:通过上述方法计算前缀索引的选择性比率,比率越高,索引越高效。(2)选择计数(DISTINCTLEFT(index_column,1))/COUNT(*),COUNT(DISTINCTLEFT(index_column,2))/COUNT(*),COUNT(DISTINCTLEFT(index_column,3))/COUNT(*)...FROM表名;注意:通过上面的语句,逐渐找到最接近(1)的前缀索引的选择性比,然后就可以使用对应的字符截取长度来制作前缀索引。5.2.2、创建前缀索引length));5.2.3使用前缀索引的注意事项前缀索引是使索引更小更快的有效方法,但MySql不能对ORDERBY和GROUPBY使用前缀索引,也不能对覆盖扫描使用前缀索引。5.3.选择合适的索引列顺序索引列的顺序在创建复合索引时非常重要。正确的索引顺序取决于使用索引的查询方法。复合索引的索引顺序可以帮助我们完成经验法则:将选择性最高的列放在索引的最前面。这个规则和前缀索引的选择性方法是一致的,但是并不代表所有组合索引的顺序都可以用这个规则来确定,需要根据具体的查询场景来确定。索引顺序。5.4聚簇索引和非聚簇索引(1)、聚簇索引聚簇索引决定了数据在物理磁盘上的物理排序。一张表只能有一个聚簇索引。如果定义了主键,InnoDB将通过主键聚合数据。如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有唯一的非空索引,InnoDB会隐式定义一个主键作为聚簇索引。聚簇索引可以大大提高访问速度,因为聚簇索引将索引和行数据存储在同一个B-Tree中,所以如果找到索引,相应的行数据也会相应的找到,但是当使用聚簇索引时在这个时间,要注意避免随机聚簇索引(一般指主键值不连续,分布范围不均匀)。如果使用UUID作为聚簇索引,性能会很差,因为UUID值的不连续性会增加大量的索引碎片和RandomI/O,最终导致查询性能急剧下降。(2)非聚集索引与聚集索引的区别在于非聚集索引不决定数据在磁盘上的物理顺序,B-Tree包含索引但不包含行数据,而行数据在B-Tree中只保存索引对应的指针指向行数据,如:上面建立在(user_name,city,age)上的索引是非聚集索引。5.5.覆盖索引如果一个索引(如:组合索引)包含了所有要查询的字段的值,则称为覆盖索引,如:SELECTuser_name,city,ageFROMuser_testWHEREuser_name='feinik'ANDage>25;因为查询是字段(user_name,city,age)都包含在组合索引的索引列中,所以使用覆盖索引查询来检查是否使用了覆盖索引。执行计划中Extra中的值可以用来证明使用了覆盖索引。索引、覆盖索引可以大大提高访问性能。5.6.如何使用索引进行排序如果在排序操作中可以使用索引进行排序,那么排序的速度可以大大提高。要使用索引进行排序,需要满足以下两点。(1)ORDERBY子句后的列顺序必须与复合索引相同,并且所有排序列的排序方向(正向/反向)必须一致(2)、要查询的字段值必须包含在索引列中,并且满足覆盖索引,举例创建组合索引ALTERTABLEuser_testADDINDEXindex_user(user_name,city,age);可以使用索引排序的情况where查询条件是索引列的第一列,并且是常量条件,那么也可以使用索引不能使用索引排序的情况(1),sex不在索引列中SELECTuser_name,city,ageFROMuser_testORDERBYuser_name,性别;(2)、排序列的方向不一致SELECTuser_name,city,ageFROMuser_testORDERBYuser_nameASC,cityDESC;(3)、查询的字段列sexSELECTuser_name,city,age,sexFROMuser_testORDERBYuser_name未包含在索引列中;(4)、where查询条件后的user_name是范围查询,所以索引的其他列不能使用SELECTuser_name,city,ageFROMuser_testWHEREuser_nameLIKE'feinik%'ORDERBYcity;(5)1.多表查询时,只有当ORDERBY后的排序字段都是第一个表中的索引列时才可以使用索引排序(需要满足以上两条规则索引排序)。例如:再创建一个用户扩展表user_test_ext,并创建uid索引。DROPTABLEIFEXISTSuser_test_ext;CREATETABLEuser_test_ext(idintAUTO_INCREMENTPRIMARYKEY,uidintNOTNULL,u_passwordVARCHAR(64)NOTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8;ALTERTABLEuser_test_extADDINDEXindex_user_ext(uid);走索引排序SELECTuser_name,city,ageFROMuser_testuLEFTJOINuser_test_extueONu.id=ue.uidORDERBYu.user_name;不走索引排序SELECTuser_name,city,ageFROMuser_testuLEFTJOINuser_test_extueONu.id=ue.uidORDERBYue.uid;6.小结本文主要讲述B+Tree树形结构的索引规则,不同索引的创建,以及如何正确创建高效的索引技术,尽可能提高查询速度。当然知乎使用索引的技巧不止这些,更多关于索引的技巧需要不断积累相关经验。