MySQL索引选择及规则整理
索引选择性就是结果个数与总个数的比值。
用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索引选择及规则整理的更多相关文章
- 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式
单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式 一 表结构如下: 万行 CREATE TABLE t_audit_operate_log ( Fid b ...
- MySQL索引选择不正确并详细解析OPTIMIZER_TRACE格式
一 表结构如下: CREATE TABLE t_audit_operate_log ( Fid bigint(16) AUTO_INCREMENT, Fcreate_time int(10) un ...
- 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式
一 表结构如下: 万行 CREATE TABLE t_audit_operate_log ( Fid bigint(16) AUTO_INCREMENT, Fcreate_time int(10 ...
- MySQL索引选择及添加原则
索引选择性就是结果个数与总个数的比值. 用sql语句表示为: SELECT COUNT(*) FROM table_name WHERE column_name/SELECT COUNT(*) FRO ...
- mysql索引 (校验规则引发的血案)
EXPLAIN SELECT a.* FROM gc_fin_rate_info a LEFT JOIN rbac_user b ON a.owner =b.id; 处理之前的情况. 虽然走了索引, ...
- 表数据量影响MySQL索引选择
现象 新建了一张员工表,插入了少量数据,索引中所有的字段均在where条件出现时,正确走到了idx_nap索引,但是where出现部分自左开始的索引时,却进行全表扫描,与MySQL官方所说的最左匹配原 ...
- 10 MySQL索引选择与使用
索引概述 每种存储引擎对每个表至少支持16个索引,总索引长度至少256字节. MyISAM和InnoDB的表默认创建BTREE索引.MEMORY引擎默认使用HASH索引,但也支持BTR ...
- 七、mysql索引选择
.myisam,bdb,innodb,memory 单表至少支持16个索引 .create index id_index on emp (id) 为emp表创建一个名为id_index的id字段的索引 ...
- MySQL索引那些事
原文链接 大家有没有遇到过慢查询的情况,执行一条SQL需要几秒,甚至十几.几十秒的时间,这时候DBA就会建议你去把查询的 SQL 优化一下,怎么优化?你能想到的就是加索引吧? 为什么加索引就查的快了? ...
随机推荐
- java考试易错题大全
常见的Java问题 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Ja ...
- Linux(1)目录
Linux目录 / :根目录, 一般只存放目录, 在Linux下只有一个根目录. 所有的东西都是从这里开始 /bin, /usr/bin :可执行的二进制文件目录, 如常用的ls, tar, mv, ...
- 删除物品[JLOI2013]
题目描述 箱子再分配问题需要解决如下问题: (1)一共有N个物品,堆成M堆. (2)所有物品都是一样的,但是它们有不同的优先级. (3)你只能够移动某堆中位于顶端的物品. (4)你可以把任意一 ...
- C语言程序设计进阶 翁恺 第4周编程练习
第4周编程练习 查看帮助 返回 第4周编程练习 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业 ...
- mysql存储过程详细讲解及完整实例下载
一.存储过程概念 1.存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集.经编译后存储在数据库 中. 2.存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给 ...
- python之禅 the zen of python
>>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is ...
- 在django中集成ckeditor富文本
目前用的比较多的富文本插件有百度的ueditor.ckeditor.kindeditor等,其中ueditor和kindeditor比较美观,ckeditor的皮肤较少.但是ueditor加载较慢,k ...
- ThinkSNS+ 基于 Laravel master 分支,从 1 到 0,再到 0.1
什么是 ThinkSNS+ 09 年,由北京的团队开发了 ThinkSNS 涉足社交开源行业.这么多年累计不少客户.2014-2016,两年都在维护和开发之前基于 TP 的 ThinkSNS , 慢慢 ...
- XP oracle32位客户端安装找不到orandce11.dll.dbl
同事在XP上装oracle客户端,遇到下面的问题,mark一下. 提示找不到:orandce11.dll.dbl 点继续还会提示这个文件:orancds11.dll.dbl 网上找到解决方法: 删除注 ...
- GBK和UTF-8互相转码
<1>.GBK ---> UTF-8 void ConvertGBKToUtf8(CString& strGBK) { , (LPCTSTR)strGBK, -, NULL, ...