MySQL之Prefix Index
来源:互联网 发布:淘宝手机壳店铺装修 编辑:程序博客网 时间:2024/05/20 14:15
作者:老王
细节决定结果!可惜人们往往无视细节的存在。很多人在给表加索引的时候,喜欢直接使用PHPMyAdmin操作,因为这样做操作简单,甚至不用记ALTER TABLE语法,用鼠标点一下就OK了,但是这样做的一个缺点是让使用者忽视了“索引长度”的存在,从而使用数据的完整长度去建立索引,这本身并没有什么逻辑错误,但是很多时候,我们并不需要使用数据的完整长度去建立索引,比如说有两个老王,一个是北京回龙观的老王,一个是上海徐家汇的老王。如果你按照数据的完整长度去建立索引以便定位老王的话,那么就要完整的索引北京回龙观和上海徐家汇这样的信息,但实际上在本例中回龙观,徐家汇这些地址信息是不必要的,只要提供一下城市信息是北京还是上海,就能定位要找的老王了,这也正是Prefix Index的含义所在,它的意义在于会大大缩减索引文件的大小,从而加快数据检索的速度。
在经典的《High Performance MySQL》里有现成的例子,我就直接拿过来用了:
CREATE TABLE sakila.city_demo(city VARCHAR(50) NOT NULL);
现在我们建立了一个测试表,如果要让测试效果明显点,至少得加入几百条数据,并让数据分布尽可能合理,这些就不提供了,大家可以自己找点实际数据测试,下面要给city字段建立索引,我们看看多长合适:
先看原始数据的汇总结果:
mysql> SELECT COUNT(*) AS cnt, city
-> FROM sakila.city_demo GROUP BY city ORDER BY cnt DESC LIMIT 10;
65: London
49: Hiroshima
48: Teboksary
48: Pak Kret
48: Yaound
47: Tel Aviv-Jaffa
47: Shimoga
45: Cabuyao
45: Callao
45: Bislig
下面看看如果按照前三个字符去汇总的话结果会是怎样:
mysql> SELECT COUNT(*) AS cnt, LEFT(city, 3) AS pref
-> FROM sakila.city_demo GROUP BY pref ORDER BY cnt DESC LIMIT 10;
483: San
195: Cha
177: Tan
167: Sou
163: al-
163: Sal
146: Shi
136: Hal
130: Val
129: Bat
可以发现按前三个字符去汇总的话,数据重复率太高了,而且选出来的东西和真实汇总结果差别太大,这时索引效率不会很好,那么按前七个字符做呢:
mysql> SELECT COUNT(*) AS cnt, LEFT(city, 7) AS pref
-> FROM sakila.city_demo GROUP BY pref ORDER BY cnt DESC LIMIT 10;
70: Santiag
68: San Fel
65: London
61: Valle d
49: Hiroshi
48: Teboksa
48: Pak Kre
48: Yaound
47: Tel Avi
47: Shimoga
结果和真实的汇总数据比较接近了,所以说在本例中,7是比较合理的索引长度。
另一种判断合理索引长度的方法是通过数据的选择度情况来判断,先看原始数据的选择度:
mysql> SELECT COUNT(DISTINCT city)/COUNT(*) FROM sakila.city_demo;
0.0312: COUNT(DISTINCT city)/COUNT(*)
再来计算一下不同长度的选择度:
mysql> SELECT COUNT(DISTINCT LEFT(city, 3))/COUNT(*) AS sel3,
-> COUNT(DISTINCT LEFT(city, 4))/COUNT(*) AS sel4,
-> COUNT(DISTINCT LEFT(city, 5))/COUNT(*) AS sel5,
-> COUNT(DISTINCT LEFT(city, 6))/COUNT(*) AS sel6,
-> COUNT(DISTINCT LEFT(city, 7))/COUNT(*) AS sel7
-> FROM sakila.city_demo;
0.0239: sel3
0.0293: sel4
0.0305: sel5
0.0309: sel6
0.0310: sel7
从结果中可以看出,随着长度的增加越来越接近原始数据的选择度,但是4、5、6、7几个选择似乎都不错,哪个更合理呢?
mysql> SELECT COUNT(*) AS cnt, LEFT(city, 4) AS pref
-> FROM sakila.city_demo GROUP BY pref ORDER BY cnt DESC LIMIT 5;
205: San
200: Sant
135: Sout
104: Chan
091: Toul
可以发现数据重复率太高了,而且选出来的东西和真实汇总结果差别太大,所以4不是一个合适的选择。
把可能的选择都尝试一下,很容易就能确定合理的长度,假如说是7,剩下的就好办了,别用PHPMyAdmin了,ALTER TABLE的语法并不难记:
mysql> ALTER TABLE sakila.city_demo ADD KEY (city(7));
还可以通过核对cardinality来判断索引长度是否合理,这个参数在SHOW INDEX FROM ...的时候能看到。
还有一点需要注意,那就是生产环境里,你的数据分布情况是在不断变化的,所以合理的索引长度也可能是在不断变化的,为了适应变化,有时候你不得不时常调整索引,但是在MySQL里,ALTER TABLE属于剧烈运动,要小心对待,为了降低ALTER TABLE建立索引对在线服务的影响,可以采用主从服务器结构,具体的描述可以参考我以前的文章:MySQL主从服务器的一些技巧。
- MySQL之Prefix Index
- MySQL之Prefix Index
- MySQL之Covering Index
- MySQL之Covering Index
- MySQL之Covering Index
- MySQL之Covering Index
- mysql 优化之index
- mysql之index(索引)
- mysql之index
- show index 之Cardinality (mysql)
- mysql优化之 Covering Index
- MySQL权限篇之INDEX
- MySQL之 SQL force Index 强制索引
- mysql数据库优化之index索引
- MySQL Study之--Index强制和忽略
- 【MySQL】性能优化之 index merge (1)
- 【MySQL】性能优化之 Index Condition Pushdown
- MySQL 优化之 index merge(索引合并)
- oracle cast 用法
- 预编译头文件 (编译问题)
- 结婚那天,坐在角落里象乞丐的人,居然是我的公婆!(转)
- java 获取系统信息及CPU的使用率
- new CSDN( );
- MySQL之Prefix Index
- 动态规划 (Dynamic Programming) 之 最长递增子序列(Longest Increase Subsequence)
- 如何在Python中调用父类的同名方法
- Flex之图表组件(4) ------ 蜡烛图表
- 浅谈Java语言接口与继承本质区别
- 隐马尔科夫模型HMM自学(转)
- 心情
- 出差
- 让linux加载当前目录的动态库