1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > mysql优化器怎么选择索引 为什么MySQL查询优化器会选择聚集主索引上的二级索引?...

mysql优化器怎么选择索引 为什么MySQL查询优化器会选择聚集主索引上的二级索引?...

时间:2023-12-29 19:54:58

相关推荐

mysql优化器怎么选择索引 为什么MySQL查询优化器会选择聚集主索引上的二级索引?...

为什么Mysql优化器在执行’select * from lookup’而没有order by子句时选择二级索引.

它只是一个侥幸,或者这是一个幕后优化,假设你添加了一个二级索引,它比主键更重要.

我希望通过主键对结果进行排序,因为扫描所有叶节点可以提供回答此查询所需的所有数据.

要重现我创建一个简单的键/值对表(注意不是auto_increment)

create table lookup (

id int not null,

primary key (id),

name varchar(25),

unique k_name (name)

) engine=innodb;

以随机非字母顺序插入一些数据

insert into lookup values(1, "Zebra"),(2, "Aardvark"),(3, "Fish"),(4,"Dog"),(5,"Cat"),(6,"Mouse");

查询数据(这是我希望以主键的顺序返回数据的地方)

mysql> select * from lookup;

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

| id | name |

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

| 2 | Aardvark |

| 5 | Cat |

| 4 | Dog |

| 3 | Fish |

| 6 | Mouse |

| 1 | Zebra |

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

6 rows in set (0.00 sec)

但事实并非如此 – 似乎已经完成了对k_name叶节点的扫描.这里显示

mysql> explain select * from lookup;

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

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

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

| 1 | SIMPLE | lookup | index | NULL | k_name | 28 | NULL | 6 | Using index |

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

1 row in set (0.00 sec)

对我来说,这说Mysql使用k_name作为覆盖索引来返回数据.如果我删除k_name索引,则以主键顺序返回数据.如果我添加另一个未索引的列,则以主键顺序返回数据.

有关我的设置的一些基本信息.

mysql> show table status like 'lookup'\G

*************************** 1. row ***************************

Name: lookup

Engine: InnoDB

Version: 10

Row_format: Compact

Rows: 6

Avg_row_length: 2730

Data_length: 16384

Max_data_length: 0

Index_length: 16384

Data_free: 0

Auto_increment: NULL

Create_time: -11-15 10:42:35

Update_time: NULL

Check_time: NULL

Collation: latin1_swedish_ci

Checksum: NULL

Create_options:

Comment:

1 row in set (0.00 sec)

mysql> select version();

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

| version() |

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

| 5.5.15-log |

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

1 row in set (0.00 sec)

解决方法:

实际上,聚集索引(也称为gen_clust_index)的填充顺序除了以rowid顺序之外没有押韵或原因.几乎不可能按id顺序订购rowid.

在InnoDB中,非聚簇索引(也称为二级索引)中的记录包含不在二级索引中的行的主键列. InnoDB使用此主键值来搜索聚簇索引中的行.

二级索引管理订单.但是,每个辅助索引条目都有一个指向正确行的主键.另外,请考虑您为k_name提到的覆盖索引方案.

现在,让我们暂时切换一下,讨论PRIMARY KEY和k_name:

问题:原始查询,主键或k_name请求的列数更多?

答案:k_name,因为它同时包含name和id(id是internal,因为它是PRIMARY KEY).覆盖索引k_name比主键更好地满足查询.

现在,如果查询是SELECT * FROM ORDER BY id,则EXPLAIN PLAN应如下所示:

mysql> explain select * from lookup order by id;

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

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

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

| 1 | SIMPLE | lookup | index | NULL | PRIMARY | 4 | NULL | 6 | |

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

1 row in set (0.00 sec)

如果没有指定顺序,MySQL Query Optimizer会选择最能满足您查询的索引.当然,k_name具有不公平的优势,因为

>表中的每一列都是单独编制索引的

>表中的每一列都是Candidate Key

> k_name不是SECONDARY INDEX,因为它是一个候选键,就像PRIMARY KEY一样.

>用户定义的聚簇索引一旦建立就不能更改行顺序

您根本无法操纵行的顺序.这是证明:

mysql> alter table lookup order by name;

Query OK, 6 rows affected, 1 warning (0.23 sec)

Records: 6 Duplicates: 0 Warnings: 1

mysql> show warnings;

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

| Level | Code | Message |

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

| Warning | 1105 | ORDER BY ignored as there is a user-defined clustered index in the table 'lookup' |

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

1 row in set (0.00 sec)

mysql> alter table lookup order by id;

Query OK, 6 rows affected, 1 warning (0.19 sec)

Records: 6 Duplicates: 0 Warnings: 1

mysql> show warnings;

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

| Level | Code | Message |

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

| Warning | 1105 | ORDER BY ignored as there is a user-defined clustered index in the table 'lookup' |

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

1 row in set (0.00 sec)

标签:mysql,innodb

来源: https://codeday.me/bug/0518/1126810.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。