首页 > 数据库 > MySQL > 正文

通过实例认识MySQL中前缀索引的用法

2024-07-24 13:07:09
字体:
来源:转载
供稿:网友

这篇文章主要通过实例来介绍MySQL中的前缀索引,包括前缀在实际使用中需要考虑到的长度问题等,需要的朋友可以参考下

今天在测试环境中加一个索引时候发现一警告

  1. root@test 07:57:52>alter table article drop index ind_article_url; 
  2. Query OK, 144384 rows affected (16.29 sec) 
  3. Records: 144384 Duplicates: 0 Warnings: 0 
  4. root@test 07:58:40>alter table article add index ind_article_url(url); 
  5. Query OK, 144384 rows affected, 1 warning (19.52 sec) 
  6. Records: 144384 Duplicates: 0 Warnings: 0 
  7. root@test 07:59:23>show warnings; 
  8. +———+——+———————————————————+ 
  9. Level | Code | Message | 
  10. +———+——+———————————————————+ 
  11. | Warning | 1071 | Specified key was too long; max key length is 767 bytes | 
  12. +———+——+———————————————————+ 
  13. 1 row in set (0.00 sec) 


用show create table article查看索引以及表结构的信息:

 

 
  1. `URL` varchar(512) default NULL COMMENT ‘外链url', 
  2. …… 
  3. KEY `ind_article_url` (`URL`(383)) 
  4. ….. 
  5. DEFAULT CHARSET=gbk 
  6. …… 
  7. drop table test; 
  8. create table test(test varchar(767) primary key)charset=latin5; 

– 成功

接下来未测试,在不同的字符集:

 

 
  1. drop table test; 
  2. create table test(test varchar(768) primary key)charset=latin5; 

– 错误

 

 
  1. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes 
  2. drop table test; 
  3. create table test(test varchar(383) primary key)charset=GBK; 

– 成功

 

 
  1. drop table test; 
  2. create table test(test varchar(384) primary key)charset=GBK; 

– 错误

 

 
  1. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes 
  2. drop table test; 
  3. create table test(test varchar(255) primary key)charset=UTF8; 

– 成功

 

 
  1. drop table test; 
  2. create table test(test varchar(256) primary key)charset=UTF8; 

– 错误

 

 
  1. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes 

MySQL的varchar索引只支持不超过768个字节 或者 768/2=384个双字节 或者 768/3=256个三字节的字段

而 GBK是双字节的,UTF-8是三字节的。

那么上面出现的原因就明了,我的字符集是为GBK为双字节,而url为512个字符,1024个字节,所以超过字符串索引的限制,报出了警告,mysql默认创建了383(766字节)长度的前缀索引。

我们知道小的索引大小不仅对空间存储,内存的降低和性能的提升有重大作用,那么在计算前缀索引的长度的时候,需要我们做出明智的选择,怎么明智?

全索引列的选择性:

 

 
  1. root@test 08:10:35>select count(distinct(url))/count(*) from article; 
  2. +——————————-+ 
  3. count(distinct(url))/count(*) | 
  4. +——————————-+ 
  5. | 0.0750 | 
  6. +——————————-+ 

对各种长度的前缀列计算其选择性:

 

 
  1. root@test 08:16:41>select count(distinct left(url,76))/count(*) url_76, 
  2. -> count(distinct left(url,77))/count(*) url_77, 
  3. -> count(distinct left(url,78))/count(*) url_78, 
  4. -> count(distinct left(url,79))/count(*) url_79, 
  5. -> count(distinct left(url,80))/count(*) url_80, 
  6. -> count(distinct left(url,81))/count(*) url_81, 
  7. -> count(distinct left(url,82))/count(*) url_82, 
  8. -> count(distinct left(url,83))/count(*) url_83, 
  9. -> count(distinct left(url,84))/count(*) url_84, 
  10. -> count(distinct left(url,85))/count(*) url_85 
  11. -> from article; 
  12. +——–+——–+——–+——–+——–+——–+——–+——–+——–+——–+ 
  13. | url_76 | url_77 | url_78 | url_79 | url_80 | url_81 | url_82 | url_83 | url_84 | url_85 | 
  14. +——–+——–+——–+——–+——–+——–+——–+——–+——–+——–+ 
  15. | 0.0747 | 0.0748 | 0.0749 | 0.0749 | 0.0749 | 0.0749 | 0.0749 | 0.0749 | 0.0749 | 0.0750 | 
  16. +——–+——–+——–+——–+——–+——–+——–+——–+——–+——–+ 
  17. 1 row in set (1.82 sec) 

我们看到选择85的长度的时候,该前缀列的选择性和全列的选择性相当了:

alter table article add index ind_article_url(url(85)),而不必选择383个字节作为前缀;

但是前缀索引还是有一点不足的地方,就是在查询语句中order by 和group by不能使用到前缀索引

 

 
  1. root@test 08:49:24>explain select id,url,deleted from article group by url; 
  2. +—-+————-+————-+——+—————+——+———+——+——–+———————————+ 
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
  4. +—-+————-+————-+——+—————+——+———+——+——–+———————————+ 
  5. | 1 | SIMPLE | article | ALL | NULL | NULL | NULL | NULL | 139844 | Using temporary; Using filesort | 
  6. +—-+————-+————-+——+—————+——+———+——+——–+———————————+ 
  7. 1 row in set (0.00 sec); 

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表