博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL执行计划explain的key_len解析
阅读量:5021 次
发布时间:2019-06-12

本文共 33381 字,大约阅读时间需要 111 分钟。

前言:当用Explain查看SQL的执行计划时,里面有列显示了 key_len 的值,根据这个值可以判断索引的长度,在组合索引里面可以更清楚的了解到了哪部分字段使用到了索引。下面演示中,表结构的合理性这边暂且不说,只是证明一下索引长度的计算方法。目前大部分博文是字符类型的索引长度计算方法,下面列举几个类型的索引长度计算方法

1、整数类型

 

(dg1)root@127.0.0.1 [mytest]> desc table_key;+---------+-------------+------+-----+---------+-------+| Field   | Type        | Null | Key | Default | Extra |+---------+-------------+------+-----+---------+-------+| id      | int(11)     | NO   |     | NULL    |       || sid     | bigint(20)  | NO   |     | 0       |       || name    | char(10)    | YES  |     | NULL    |       || age     | tinyint(4)  | YES  |     | NULL    |       || sex     | tinyint(4)  | NO   |     | NULL    |       || address | varchar(10) | YES  | MUL | NULL    |       |+---------+-------------+------+-----+---------+-------+6 rows in set (0.01 sec)(dg1)root@127.0.0.1 [mytest]>create index age_index on table_key (age);来看看tinyint类型的索引长度,在NOT NULL 和 NULL 的时候 分别是1和2,tinyint字段长度为1,因为NULL 需要额外一个字节标记为空(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where age=38;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+|  1 | SIMPLE      | table_key | ref  | age_index     | age_index | 1       | const |    1 |   100.00 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> alter table table_key modify age  tinyint(4);(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where age=38;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+|  1 | SIMPLE      | table_key | ref  | age_index     | age_index | 2       | const |    1 |   100.00 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+----------+-------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> 看看bigint类型的索引长度,同样是 NOT NULL 和 NULL值的时候,分别是8和9,聪明的你应该知道了,bigint长度为8。(dg1)root@127.0.0.1 [mytest]> alter table table_key add key sid_index (sid);Query OK, 0 rows affected (0.04 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 8       | const |    1 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify sid bigint(20);Query OK, 0 rows affected (0.08 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 9       | const |    1 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+1 row in set (0.00 sec)看看smallint类型索引长度,同样是 NOT NULL 和 NULL值的时候,分别是2和3 smallint长度为2,允许为空需要一个字节标记 (dg1)root@127.0.0.1 [mytest]> alter table table_key modify sid smallint not null default 0;Query OK, 9 rows affected (0.04 sec)Records: 9  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 2       | const |    1 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]> alter table table_key modify sid smallint ;Query OK, 0 rows affected (0.07 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 3       | const |    1 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+1 row in set (0.00 sec)看看mediumint类型索引长度,同样是 NOT NULL 和 NULL值的时候,分别是3和4(dg1)root@127.0.0.1 [mytest]> alter table table_key modify sid mediumint NOT NULL;Query OK, 0 rows affected (0.06 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 3       | const |    1 | NULL  |+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify sid mediumint ;

 Query OK, 0 rows affected (0.06 sec)

Records: 0  Duplicates: 0  Warnings: 0

(dg1)root@127.0.0.1 [mytest]> desc select * from table_key where sid=6;

+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+

| id | select_type | table     | type | possible_keys | key       | key_len | ref   | rows | Extra |

+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+

|  1 | SIMPLE      | table_key | ref  | sid_index     | sid_index | 4       | const |    1 | NULL  |

+----+-------------+-----------+------+---------------+-----------+---------+-------+------+-------+

1 row in set (0.00 sec)

(dg1)root@127.0.0.1 [mytest]>

 整数类型索引长度跟字段长度有关,如果允许为空,需要额外一个字节去标记为空

2.浮点数类型

表结构 CREATE TABLE `table_key1` (`id`  int NOT NULL AUTO_INCREMENT ,`c1`  float NOT NULL ,`c2`  double NOT NULL ,`c3`  decimal NOT NULL ,`c4`  date NOT NULL ,`c5`  timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP ,`c6`  datetime NOT NULL ,PRIMARY KEY (`id`)) 看看float类型的索引长度,NOT NULL和NULL的时候,分别是4和5(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c1 = '3.22';+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c1_index      | c1_index | 4       | const |    8 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]> alter table table_key1 modify c1 float;Query OK, 0 rows affected (0.05 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c1 = '3.22';+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c1_index      | c1_index | 5       | const |    8 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set (0.00 sec)看看double类型的索引长度,NOT NULL和NULL的时候,分别是8和9(dg1)root@127.0.0.1 [mytest]> alter table table_key1 add key c2_index (c2);Query OK, 0 rows affected (0.04 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c2 = '3.22';+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key1 | ref  | c2_index      | c2_index | 8       | const |    1 | NULL  |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]> alter table table_key1 modify c2 double;Query OK, 0 rows affected (0.03 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c2 = '3.22';+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key1 | ref  | c2_index      | c2_index | 9       | const |    1 | NULL  |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@127.0.0.1 [mytest]>

3、看看时间类型

看看date类型的索引长度,在NOT NULL和NULL的时候,分别是3和4(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c4 = '2015-05-06';+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c4_index      | c4_index | 3       | const |    4 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set, 3 warnings (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key1 modify c4 date;Query OK, 0 rows affected (0.09 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c4 = '2015-05-06';+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c4_index      | c4_index | 4       | const |    4 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set, 3 warnings (0.00 sec)(dg1)root@127.0.0.1 [mytest]> 在timestamp类型的时候索引长度,在NOT NULL 和 NULL的时候,分别是4和5(dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c5 = '2015-05-06 11:23:21' ;+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c5_index      | c5_index | 4       | const |    5 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set, 3 warnings (0.00 sec)(dg1)root@127.0.0.1 [mytest]> dg1)root@127.0.0.1 [mytest]> alter table table_key1 modify c5 timestamp ON UPDATE CURRENT_TIMESTAMP ;Query OK, 0 rows affected (0.06 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> desc select * from table_key1 where c5 = '2015-05-06 110:23:21';+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra                 |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+|  1 | SIMPLE      | table_key1 | ref  | c5_index      | c5_index | 5       | const |    5 | Using index condition |+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+1 row in set, 3 warnings (0.00 sec)(dg1)root@127.0.0.1 [mytest]> ##############################在大家认识里datetime是八个字节的长度,下面就来看看,是不是真的这样 (dg1)root@localhost [mytest]> alter table table_key1 modify c6 datetime not null;Query OK, 0 rows affected (0.03 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@localhost [mytest]> desc select * from table_key1 where c6 = '2015-05-06 11:10:36';+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key1 | ref  | c6_index      | c6_index | 5       | const |    1 | NULL  |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+1 row in set (0.00 sec)(dg1)root@localhost [mytest]> alter table table_key1 modify c6 datetime  null;Query OK, 0 rows affected (0.06 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@localhost [mytest]> desc select * from table_key1 where c6 = '2015-05-06 11:10:36';+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+|  1 | SIMPLE      | table_key1 | ref  | c6_index      | c6_index | 6       | const |    1 | NULL  |+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+1 row in set (0.00 sec)颠覆了我们认识,datetime不是8个字节么,下面来看一下MySQL的版本,没错MySQL5.6是datetime长度是5个字节(dg1)root@localhost [mytest]> \s--------------mysql  Ver 14.14 Distrib 5.6.22, for linux-glibc2.5 (x86_64) using  EditLine wrapperConnection id:        3Current database:    mytestCurrent user:        root@localhostSSL:            Not in useCurrent pager:        stdoutUsing outfile:        ''Using delimiter:    ;Server version:        5.6.22-log MySQL Community Server (GPL)Protocol version:    10Connection:        Localhost via UNIX socketServer characterset:    gbkDb     characterset:    gbkClient characterset:    gbkConn.  characterset:    gbkUNIX socket:        /opt/app/mysql/mysql3307.socketUptime:            4 min 47 secThreads: 1  Questions: 19  Slow queries: 0  Opens: 75  Flush tables: 1  Open tables: 64  Queries per second avg: 0.066--------------(dg1)root@localhost [mytest]> 那么真的是这样么,
(dg1)root@localhost [mytest]>alter table table_key1 change c6 c6 datetime(6) not null ;
(dg1)root@localhost [mytest]>explain select * from table_key1 where c6='2015-05-06 11:13:12.000000';

  +----+-------------+------------+------------+------+---------------+----------+---------+-------+------+----------+-------+

  | id | select_type | table      | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
  +----+-------------+------------+------------+------+---------------+----------+---------+-------+------+----------+-------+
  | 1  | SIMPLE      | table_key1 | NULL       | ref  | c6_index      | c6_index | 8       | const | 1    | 100.00   | NULL  |
  +----+-------------+------------+------------+------+---------------+----------+---------+-------+------+----------+-------+
  1 row in set, 1 warning (0.00 sec)

 

 小结:在MySQL5.6版本,是否还得使用timestamp类型应该是仁者见仁智者见智的问题了,datetime不存毫秒时候五个字节,因为官方文档说了,5.6.4以上版本,时间和毫秒分开存储了。timestamp范围比较窄(1970-2037年),不排除后续版本会修改其范围值

 4.字符类型

表结构,字符集是UTF8(dg1)root@127.0.0.1 [mytest]> desc table_key;+---------+-------------+------+-----+---------+-------+| Field   | Type        | Null | Key | Default | Extra |+---------+-------------+------+-----+---------+-------+| id      | int(11)     | NO   |     | NULL    |       || sid     | bigint(20)  | NO   |     | 0       |       || name    | char(10)    | YES  |     | NULL    |       || age     | tinyint(4)  | YES  |     | NULL    |       || sex     | tinyint(4)  | NO   |     | NULL    |       || address | varchar(10) | YES  | MUL | NULL    |       |+---------+-------------+------+-----+---------+-------+6 rows in set (0.01 sec)看看定长字符类型char的索引长度,在NOT NULL 和NULL中分别为10*3和10*3+1(dg1)root@127.0.0.1 [mytest]> alter table table_key add index name_index (name);Query OK, 0 rows affected (0.01 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan';+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_index    | name_index | 30      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify name char(10);Query OK, 0 rows affected (0.05 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan';+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_index    | name_index | 31      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)看看变长长字符类型varchar的索引长度,在NOT NULL 和NULL中分别为10*3+2和10*3+2+1(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai';+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | address_index | address_index | 32      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.01 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify address varchar(10);Query OK, 0 rows affected (0.10 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai';+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | address_index | address_index | 33      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]>
修改字符集为GBK,再来看看(dg1)root@127.0.0.1 [mytest]> ALTER TABLE `table_key` DEFAULT CHARACTER SET=gbk COLLATE=gbk_chinese_ci;(dg1)root@127.0.0.1 [mytest]> ALTER database `mytest` DEFAULT CHARACTER SET=gbk COLLATE=gbk_chinese_ci;(dg1)root@127.0.0.1 [mytest]> show global variables like '%char%';+--------------------------+--------------------------------+| Variable_name            | Value                          |+--------------------------+--------------------------------+| character_set_client     | gbk                            || character_set_connection | gbk                            || character_set_database   | gbk                            || character_set_filesystem | binary                         || character_set_results    | gbk                            || character_set_server     | gbk                            || character_set_system     | utf8                           || character_sets_dir       | /opt/app/mysql/share/charsets/ |+--------------------------+--------------------------------+8 rows in set (0.00 sec)奇怪了,为什么还是10*3+2+1呢,是因为字段的字符集还没修改过来(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai';+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | address_index | address_index | 33      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.01 sec)(dg1)root@127.0.0.1 [mytest]> ALTER TABLE `table_key` MODIFY COLUMN `name`  char(10) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL , DEFAULT CHARACTER SET=gbk COLLATE=gbk_chinese_ci;Query OK, 9 rows affected (0.04 sec)Records: 9  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> ALTER TABLE `table_key` MODIFY COLUMN `address`  char(10) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL , DEFAULT CHARACTER SET=gbk COLLATE=gbk_chinese_ci;Query OK, 9 rows affected (0.03 sec)Records: 9  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai';+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | address_index | address_index | 21      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify address varchar(10);Query OK, 9 rows affected (0.04 sec)Records: 9  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai';+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | address_index | address_index | 23      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+---------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.01 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan';+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_index    | name_index | 20      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> (dg1)root@127.0.0.1 [mytest]> alter table table_key modify name char(10);Query OK, 0 rows affected (0.00 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan';+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_index    | name_index | 21      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+---------------+------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.01 sec)
来看看复合索引的key_len,(刚才测试GBK字符集,字符集转换成GBK了)
(dg1)root@127.0.0.1 [mytest]> desc table_key;+---------+-------------+------+-----+---------+-------+| Field   | Type        | Null | Key | Default | Extra |+---------+-------------+------+-----+---------+-------+| id      | int(11)     | NO   |     | NULL    |       || sid     | bigint(20)  | NO   |     | 0       |       || name    | char(10)    | NO   |     |         |       || age     | tinyint(4)  | YES  |     | NULL    |       || sex     | tinyint(4)  | NO   |     | NULL    |       || address | varchar(10) | NO   | MUL |         |       |+---------+-------------+------+-----+---------+-------+6 rows in set (0.01 sec)
(dg1)root@127.0.0.1 [mytest]> alter table table_key drop index name_index;Query OK, 0 rows affected (0.01 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> alter table table_key drop index address_index;Query OK, 0 rows affected (0.01 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> alter table table_key add index name_address_index (name,address);Query OK, 0 rows affected (0.02 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where address='shanghai' and name='zhangsan';+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys      | key                | key_len | ref         | rows | filtered | Extra                 |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_address_index | name_address_index | 42      | const,const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)看看复合索引的长度,因为能全部使用到组合索引,所以是:2*(10)+2*(20)+2=42,下面将name字段允许为空,再来看看(dg1)root@127.0.0.1 [mytest]> alter table table_key modify name char(10); (dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan' and address='shanghai';+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys      | key                | key_len | ref         | rows | filtered | Extra                 |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_address_index | name_address_index | 43      | const,const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)
看看复合索引的长度,因为能全部使用到组合索引,所以是:2*(10)+1+2*(20)+2=43
(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan';+----+-------------+-----------+------+--------------------+--------------------+---------+-------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys      | key                | key_len | ref   | rows | filtered | Extra                 |+----+-------------+-----------+------+--------------------+--------------------+---------+-------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_address_index | name_address_index | 21      | const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+--------------------+--------------------+---------+-------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)那么我们来看看部分使用复合索引:2*(10)+1,将address设置为允许为空,再来看看(dg1)root@127.0.0.1 [mytest]> alter table table_key modify address varchar(10);Query OK, 0 rows affected (0.04 sec)Records: 0  Duplicates: 0  Warnings: 0(dg1)root@127.0.0.1 [mytest]> explain extended select * from table_key where name='zhangsan' and address='shanghai';+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+| id | select_type | table     | type | possible_keys      | key                | key_len | ref         | rows | filtered | Extra                 |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+|  1 | SIMPLE      | table_key | ref  | name_address_index | name_address_index | 44      | const,const |    1 |   100.00 | Using index condition |+----+-------------+-----------+------+--------------------+--------------------+---------+-------------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)(dg1)root@127.0.0.1 [mytest]> 这时候key_len=2*(10)+1+2*(10)+2+1=44

 

总结:

1.整数类型,浮点数类型,时间类型的索引长度

NOT NULL=字段本身的字段长度

NULL=字段本身的字段长度+1,因为需要有是否为空的标记,这个标记需要占用1个字节

datetime类型在5.6中字段长度是5个字节

2.字符类型

 

varchr(n)变长字段且允许NULL    =  n * ( utf8=3,gbk=2,latin1=1)+1(NULL)+2varchr(n)变长字段且不允许NULL  =  n * ( utf8=3,gbk=2,latin1=1)+2char(n)固定字段且允许NULL      =  n * ( utf8=3,gbk=2,latin1=1)+1(NULL)char(n)固定字段且允许NULL      =  n * ( utf8=3,gbk=2,latin1=1)变长字段需要额外的2个字节(VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节),所以VARCAHR索引长度计算时候要加2),固定长度字段不需要额外的字节。而null都需要1个字节的额外空间,所以索引字段最好不要为NULL,因为NULL让统计更加复杂,并且需要额外的存储空间。这个结论在此得到了证实,复合索引有最左前缀的特性,如果复合索引能全部使用上,则是复合索引字段的索引长度之和,这也可以用来判定复合索引是否部分使用,还是全部使用。

 

转载于:https://www.cnblogs.com/LMySQL/p/4525867.html

你可能感兴趣的文章
badboy录制兼容性有趣测试
查看>>
sqlite字段类型
查看>>
Verilog之VGA
查看>>
java反射
查看>>
C++ 引用
查看>>
lab -- 美国大学实验室
查看>>
tiled工具使用
查看>>
MySQL 的性能(下篇)—— 性能优化方法
查看>>
xctf --Hctf2014 Quals write up
查看>>
一个完整的大作业
查看>>
自定义Java Annotations实例以及用Java Reflection来解析自定义的Annotation
查看>>
【ADB命令第三篇】教你删除忘记的密码!
查看>>
Chapter16— A thread's Stack
查看>>
CoreLocation详解
查看>>
Android App 性能评测与调优
查看>>
【电子基础】单片机定时器实用方法总结
查看>>
Prism4文档翻译(第二章 全部内容)
查看>>
智东西公开课干货盘点 | 全方位解析人脸识别商用落地
查看>>
CSS学习笔记(四):布局
查看>>
JAVA 基于TCP协议的一对一,一对多文件传输实现
查看>>