mysql优化-索引篇(草稿)
说到索引优化,你是否只能说出:在where字段加索引,唯一索引,联合索引,普通索引等等。
可是,你知道B-tree,T-tree或者hash索引么?
hash索引在memory使用。
最好的设计是索引覆盖! 需要精心设计,不是一定可以达成的
hash索引劣势
1 随机读取 对机械硬盘来说,顺序读取是随机读取速度的几十倍!
2 不支持左前缀 存储helloworld --索引字段 like "hello%"-- hash(hello) 和 hash(helloworld)无任何联系
3 排序支持不好 因为1,不连续,根据hash存放而不是排序顺序!
4 范围支持不好 因为1,不连续,根据hash存放而不是范围!
5 必须回行!因为很难逆运算
hash索引的劣势就是B-tree的优势!
B-tree常见误区
误区1:
select * from xxx where x1=x and x2=y...
x1和x2有独立的索引,只用其一!而不是全部使用!!
可以建立多列索引
误区2:
多列索引,where每一个字段用索引?
要满足左前缀!
多列索引具体使用规则例:
**********************************
1、index(a,b,c)
2、where a = 1 yes
3、where b=2 ,where c=3 no
4、where a=1 and b=2 yes
5、where a=1 and b=2 and c=3 yes
6、where a=1 and c=2 a可以
7、where a=1 and b>5 and c=2 a,b可以,c不可以
8、where a=1 and b like "xxx%" and c =2 a,b可以,c不可以
7和8是因为b发生了范围,之后就不可以使用
************************************
多列索引使用规则:
1 要满足左前缀!
2 范围匹配(like or >)之后不可用!
帮助理解的案例:桥接板!
mysiam与innodb存储引擎的不同:
mysiam索引的指针指向物理数据地址
innodb索引的指针指向主键索引 因为物理存储上物理数据挂在主键上
问题 innodb如果没设置主键呢?
1 如果没人为设置主键,则系统选取unique,如果没有unique,则系统声称一个内部rowid作为主键。
这种类型的索引就是--聚簇索引!
=========问题分割线===============
disable keys 作用?
官方描述:让MySQL停止更新 MyISAM表中的非唯一索引
1 更新----并不是禁用 而是停止更新 (试验,待做!)
2 myisam表
3 非唯一
==============================
高性能索引:
一 长度的选择
考虑因素: 区分度,长度!
测试:select count(distinct left(字段,长度))/count(*) from xxx;
不停变换长度来区分!
结论:区分度>0.1就合格!
技巧篇:
对于左前缀不易区分的字符串,可以:
1,倒转字符串来存! 左截取
2,hash(url),可以用crc32等 针对hash_url 来降低长度
二 多列索引顺序选择:
查询频率(更优先考虑)和区分度
区分度测试: select count(distinct 索引字段)/count(*) from xxx;
结论:区分度>0.1就合格!
三 聚簇索引
B-tree树的结点上就存储数据,而不是指向数据的指针(myisam)。
innodb就用的聚簇索引。
页分裂:
innodb的概念,以及试验证明。
结论:聚簇索引最好顺序存取。
虽然是随机写入,但select 的时候是按主键顺序的!!!
四 极限优化法--索引覆盖
作用:防止回行!
问:如何添加索引?
答:嗯。。在where字段加索引。。。这远远不够!!!!!
在常搜索的字段上也要加索引,和where字段一起构成多列索引!可以防止回行!理解原理就不难了啊。。。
innodb啊!陷阱啊!!!!独立索引也可能会引用到主键啊啊!!!
五:延迟关联
select * from xxx where name like "%x%";
select a.* from xxx t1 inner join (select id from xxx where name like "%x%") t2 on t1.id =t2.id;
第二种做法使用了延迟关联,针对innodb!语句复杂,但速度却稍占优势
总结:
内层查询只沿着索引层找出主键id,一次性读值。
语句1是每找到一个id,就读值。
这只是一个在innodb中的小技巧! 适用于内存查找比较少!
疑问: 是只再innodb上还是myisan也会去物理层读取?(试验,待做)
mysql引擎参数调优:缓冲神马的有时间再写,这么多参数记不住啊记不住!
nnodb_flush_method = O_SYNC/O_DSYNC(unix) 如果是linux可以直接设置为O_DIRECT
innodb和系统打交道的一个参数。