索引选择性就是结果个数与总个数的比值。

用sql语句表示为:

SELECT COUNT(*) FROM table_name WHERE column_name/SELECT COUNT(*) FROM table_name

一般来说(例如书 “SQL Tuning“),如果选择性超过 20% 那么全表扫描比使用索引性能更优。

但MySQL是没有计算索引的选择性的,只是预测逻辑IO操作的数量,因此对于MySQL索引要慎重选择。

举个栗子,tinyint类型的列,用以保存性别,就算用上“保密”和“变性”2项,选择性也最小也才25%,因此也就没有设置索引的必要了。

以下是整理出来的规则,以供参考:(由于很多实际项目都是查询操作占了绝大部分,因此不必太过呆板)

1、选择维度高的列

2、选择 where,on,group by,order by 中出现的列

3、选择较小的数据列,这样的索引文件更小,同时可装载更多的索引键

4、为较长的字符串使用前缀索引

5、组合索引能减低索引文件的大小,使用速度也优于多个单列索引

6、切勿滥用索引,因为除了磁盘空间的开销外,每次增删改都需要重新建立索引

7、索引不会包含有NULL值的列(若组合索引包含NULL值的列则整个组合索引无效)

另外,使用索引应当尽量避免 “OR” 、“否定查询” 、“模糊查询”、“NOT IN”、“<>” 等操作!

注意:前缀索引和组合索引是建立索引的一种技巧,并非索引类型。

组合索引

假设test表中有a,b,c三个列。

ALTER TABLE test ADD INDEX abc(a,b,c);

相当于分别建立了

a,b,c

a,b

a

这样的3组索引,也是“最左前缀”这个规则的结果。

举个使用该组合索引的栗子:

SELECT * FROM test WHERE a="1" AND b="2" SELECT * FROM test WHERE a="1"

以下则用不到索引:

SELECT * FROM test WHERE b="1" AND c="2" SELECT * FROM test WHERE c="1"

因此组合索引有一定优势,但在使用上需谨慎。

前缀索引

MySQL 前缀索引能有效减小索引文件的大小,提高索引的速度。但是前缀索引也有它的坏处:MySQL 不能在 ORDER BY 或 GROUP BY 中使用前缀索引,也不能把它们用作覆盖索引(Covering Index)。

语法如下:

ALTER TABLE table_name ADD KEY column_name(prefix_length);

建立前缀索引的关键在于"prefix_length"这个参数,并且前缀索引的选择性上也有一点特殊。

前缀索引的选择性公式为:SELECT COUNT(DISTINCT column_name)/COUNT(*) FROM table_name

继续举栗子!

现在有个user表,列 family_name varchar(50) 保存的是英文姓氏(我也想用中文姓名来距离,但是不大适合,看下去就明白了。。。)

要取得设置前缀索引最理想的"prefix_length",我们首先要取得整列的选择性,如下:

SELECT COUNT(DISTINCT family_name)/COUNT(*) FROM user;

假设这里得到值是0.188。

然后我们继续去看看该列前1个字符的选择性又是多少

SELECT COUNT(DISTINCT LEFT(family_name,1))/COUNT(*) FROM user;

假设这里得到的结果是0.532,和整列的选择性出入太大,不可取,继续:

SELECT COUNT(DISTINCT LEFT(family_name,2))/COUNT(*) FROM user;

SELECT COUNT(DISTINCT LEFT(family_name,3))/COUNT(*) FROM user;

...

假设直接到“prefix_length”为5时,得到的值为0.189,非常接近!

而取6时得到的值为0.18891,这个选择性和5并没有太大的偏差。

再结合减少索引文件大小的这个思路

“prefix_length”值设置为5才是此处设置前缀索引的最优方案!

选择性讲完,还得再讲清楚这个前缀索引该怎么用!

书接上面的栗子~

正确的用法如下:

SELECT * FROM user WHERE family_name LIKE "lee%";

SELECT * FROM user WHERE family_name LIKE "david%";

以下则用不上该索引:
SELECT * FROM user WHERE family_name LIKE "_ee%";

SELECT * FROM user WHERE family_name LIKE "%en%";

SELECT * FROM user WHERE family_name LIKE "%ar%";

注意:SQL的模式缺省是忽略大小写的!

另外,“_”代表一个字符,“%”代表任意多个字符!

PS:如存在错误或不恰当之处,请不吝指正!

MySQL索引选择及规则整理的更多相关文章

  1. 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式     一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid b ...

  2. MySQL索引选择不正确并详细解析OPTIMIZER_TRACE格式

    一 表结构如下: CREATE TABLE t_audit_operate_log (  Fid bigint(16) AUTO_INCREMENT,  Fcreate_time int(10) un ...

  3. 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

    一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid bigint(16) AUTO_INCREMENT,  Fcreate_time int(10 ...

  4. MySQL索引选择及添加原则

    索引选择性就是结果个数与总个数的比值. 用sql语句表示为: SELECT COUNT(*) FROM table_name WHERE column_name/SELECT COUNT(*) FRO ...

  5. mysql索引 (校验规则引发的血案)

    EXPLAIN SELECT a.* FROM gc_fin_rate_info  a LEFT JOIN rbac_user b ON a.owner =b.id; 处理之前的情况. 虽然走了索引, ...

  6. 表数据量影响MySQL索引选择

    现象 新建了一张员工表,插入了少量数据,索引中所有的字段均在where条件出现时,正确走到了idx_nap索引,但是where出现部分自左开始的索引时,却进行全表扫描,与MySQL官方所说的最左匹配原 ...

  7. 10 MySQL索引选择与使用

    索引概述     每种存储引擎对每个表至少支持16个索引,总索引长度至少256字节.     MyISAM和InnoDB的表默认创建BTREE索引.MEMORY引擎默认使用HASH索引,但也支持BTR ...

  8. 七、mysql索引选择

    .myisam,bdb,innodb,memory 单表至少支持16个索引 .create index id_index on emp (id) 为emp表创建一个名为id_index的id字段的索引 ...

  9. MySQL索引那些事

    原文链接 大家有没有遇到过慢查询的情况,执行一条SQL需要几秒,甚至十几.几十秒的时间,这时候DBA就会建议你去把查询的 SQL 优化一下,怎么优化?你能想到的就是加索引吧? 为什么加索引就查的快了? ...

随机推荐

  1. yum 源问题

    YUM源搭建 1.yum源是yum安装的获取源地,yum  = 红帽包管理 echo /dve/sr0 /media ios9660 defaults 0 0 >> /etc/fstab ...

  2. JMeter学习笔记-JForum环境搭建

    一.准备环境 1. Java环境安装配置(JDK+JRE+环境变量) 2. Tomcat下载安装 下载地址: 安装教程:http://jingyan.baidu.com/article/870c6fc ...

  3. 时间戳,取值问题 and 倒计时的前端处理

    JavaScript 获取当前时间戳: 第一种方法: var timestamp = Date.parse(new Date()); 获取的时间戳是把毫秒改成000显示, 结果:12809773300 ...

  4. 暑假OI规划

    为了准备11月的NOIP(最好能到550+)暑假要认真的刷题: 1.NOIP的原题 2.USACO历年的GOLD 3.CF的比赛 4.刷几本书 5.带着做bzoj(lydsy) 6.少玩游戏

  5. 《撸轮子系列》之LoadPE

    前言 我新书<Python爬虫开发与项目实战>出版了. 这本书包括基础篇,中级篇和深入篇三个部分,不仅适合零基础的朋友入门,也适合有一定基础的爬虫爱好者进阶,如果你不会分布式爬虫,不会千万 ...

  6. vue如何封装自己需要的方法

    因为现在vue的流行,vue的各种插件都出来了,我们公司也是使用vue做项目,我自己在做项目的时候自己去琢磨了其他的插件以及结合自己对vue和es2015的理解,自己找的了一种在vue中使用封装方法的 ...

  7. tomcat websocket 实现网页在线即时聊天

    背景介绍 近一个月完成了公司的一个项目,负责即时聊天部分 寻找了一下,决定使用websocket,要问原因的话,因为tomcat 自带相关消息收发的API,用起来方便 闲话少叙,进入实现步骤 使用工具 ...

  8. C/C++ 知识点---字符串函数

    1.strcpy字符串拷贝2.strcmp字符串比较3.strstr字符串查找4.strDelChar字符串删除字符5.strrev字符串反序6.memmove拷贝内存块7.strlen字符串长度 - ...

  9. WebApi 的CRUD 的方法的应用

    一.最近一直在忙于开发公司的新的项目和搭建公司的框架,也好久没有写博客了.对于RaidDevelopmentFramework 我有着自己的见解在应用到实际的框架中确实挺好用的,但是还是存在一部分的问 ...

  10. ELK搭建指南(linux及Windows)

    当前公司系统使用mongodb记录日志,最近想对日志做可视化分析,尝试了exceptionless,感觉扩展性不高,所以尝试搭建elk,过程如下: ELK核心由三部分组成: Elasticsearch ...