节点|曾经,我以为我很懂MySQL索引...( 四 )
比如索引 abc_index:(a , b , c)是 a , b , c 三个字段的联合索引 , 下列 sql 执行时都无法命中索引 abc_index 的 。
- select * from table where c = '1';
- select * from table where b ='1' and c ='2';
- select * from table where a = '1';
- select * from table where a = '1' and b = '2';
- select * from table where a = '1' and b = '2' and c='3';
是的 , 索引 abc_index:(a , b , c) , 只会在(a)、(a , b)、(a , b , c)三种类型的查询中使用 。
其实这里说的有一点歧义 , 其实(a , c)也会走 , 但是只走 a 字段索引 , 不会走 c 字段 。
另外还有一个特殊情况说明下 , 下面这种类型的也只会有 a 与 b 走索引 , c 不会走 。
- select * from table where a = '1' and b > '2' and c='3';
最左前缀:顾名思义 , 就是最左优先 , 上例中我们创建了 a_b_c 多列索引 , 相当于创建了(a)单列索引 , (a , b)组合索引以及(a , b , c)组合索引 。
因此 , 在创建多列索引时 , 要根据业务需求 , where 子句中使用最频繁的一列放在最左边 。
④索引下推优化
还是索引 name_age_index , 有如下 sql:
- select * from table where name like '陈%' and age > 26;
- 命中 name_age_index 联合索引 , 查询所有满足 name 以"陈"开头的数据 ,然后回表查询所有满足的行 。
- 命中 name_age_index 联合索引 , 查询所有满足 name 以"陈"开头的数据 , 然后顺便筛出 age>20 的索引 , 再回表查询全行数据 。
使用索引时的注意事项
①索引不会包含有 null 值的列
只要列中包含有 null 值都将不会被包含在索引中 , 复合索引中只要有一列含有 null 值 , 那么这一列对于此复合索引就是无效的 。 所以我们在数据库设计时建议不要让字段的默认值为 null 。
②使用短索引
对串列进行索引 , 如果可能应该指定一个前缀长度 。
例如 , 如果有一个 char(255)的列 , 如果在前 10 个或 20 个字符内 , 多数值是惟一的 , 那么就不要对整个列进行索引 。 短索引不仅可以提高查询速度而且可以节省磁盘空间和 I/O 操作 。
③索引列排序
查询只使用一个索引 , 因此如果 where 子句中已经使用了索引的话 , 那么 order by 中的列是不会使用索引的 。
因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序 , 如果需要最好给这些列创建复合索引 。
④like 语句操作
一般情况下不推荐使用 like 操作 , 如果非使用不可 , 如何使用也是一个问题 。 like “%陈%” 不会使用索引而 like “陈%”可以使用索引 。
⑤不要在列上进行运算
这将导致索引失效而进行全表扫描 , 例如:
- SELECT * FROM table_name WHERE YEAR(column_name)<2017;
这不属于支持的范围查询条件 , 不会使用索引 。
我的体会
曾经 , 我一度以为我很懂 MySQL 。
刚入职那年 , 我还是个孩子 , 记得第一个需求是做个统计接口 , 查询近两小时每隔 5 分钟为一时间段的网站访问量 , JSONArray 中一共返回 24 个值 , 当时菜啊 , 写了个接口循环二十四遍 , 发送 24 条 SQL 去查(捂脸) 。
推荐阅读
- 沙面|广州第一知名小岛,曾经领事馆林立,遍地都是洋建筑
- 情感|让男人爱你如初的妙招:“拾掇”
- |员工轮休,只发最低工资,曾经的赴美第一股,华晨汽车为何沦落至此?
- |这三座城市曾经是两广总督府驻地,一座名气很大,两座默默无闻
- 古村记|青海海西7处小众古址,在高原风光中寻找曾经记忆
- 威海|中韩文化艺术节点亮威海夜空!记者探秘“山东消费年”
- 情感解压台|爱你太累,想念太苦,我熬不住了
- Veyron|布加迪设计师最喜欢这6台威航,国内曾经有2台,每台都有故事
- 元稹|曾经沧海难为水?元稹:婚姻是场权力的游戏
- 明朝|明朝覆灭之前,左良玉手握80万大军,为何选择攻打曾经的自己人