为什么它包含“使用位置”?

时间:2017-10-11 02:41:16

标签: mysql sql

这是我的表架构。

CREATE TABLE `usr_block_phone` (
    `usr_block_phone_uid` BIGINT (20) UNSIGNED NOT NULL AUTO_INCREMENT,
    `time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `usr_uid` INT (10) UNSIGNED NOT NULL,
    `block_phone` VARCHAR (20) NOT NULL,
    `status` INT (4) NOT NULL,
    PRIMARY KEY (`usr_block_phone_uid`),
    KEY `block_phone` (`block_phone`),
    KEY `usr_uid_block_phone` (`usr_uid`, `block_phone`) USING BTREE,
    KEY `usr_uid` (`usr_uid`) USING BTREE
) ENGINE = INNODB DEFAULT CHARSET = utf8

这是我的SQL

SELECT
    ubp.usr_block_phone_uid
FROM
    usr_block_phone ubp
WHERE
    ubp.usr_uid = 19
AND ubp.block_phone = '80000000001'

顺便说一句,当我运行“EXPLAIN”时,我得到的结果如下。

+------+-------------+-------+------+-----------------------------------------+---------------------+---------+-------------+------+--------------------------+
| id   | select_type | table | type | possible_keys                           | key                 | key_len | ref         | rows | Extra                    |
+------+-------------+-------+------+-----------------------------------------+---------------------+---------+-------------+------+--------------------------+
|    1 | SIMPLE      | ubp   | ref  | block_phone,usr_uid_block_phone,usr_uid | usr_uid_block_phone | 66      | const,const |    1 | Using where; Using index |
+------+-------------+-------+------+-----------------------------------------+---------------------+---------+-------------+------+--------------------------+

为什么索引usr_uid_block_phone无效? 我只想使用using index

此表现在有20000行。

2 个答案:

答案 0 :(得分:1)

实际使用了您的索引,请参阅key列。目前查询看起来很好,执行计划也很好。

使用它至少填充一百(并确保您仍然使用仅过滤一行的谓词)。

一般建议:除非你自己是一个mysql dbms开发人员,否则几乎无法预测优化器在特定情况下的行为。因此,尝试尽可能接近(在数据的大小和质量方面)的数据集总是更好。

答案 1 :(得分:1)

WHERE子句(usr_uidblock_phone)中使用的两列都存在于usr_uid_block_phone索引中,这使得它成为可能用于处理查询。更重要的是,它选择了 索引,但由于表中的行数很少,MySQL决定不使用索引的速度更快。

原因在于SELECT子句中的表达式:

SELECT
    ubp.usr_block_phone_uid

因为所选索引中不存在列usr_block_phone_uid,所以为了处理查询,MySQL需要同时读取索引(以确定哪些行符合WHERE条件)表数据(以获取这些行的列usr_block_phone_uid的值)。

只读表数据并使用WHERE条件查找匹配的行并获取其usr_block_phone_uid列更快。它需要从一个地方读取存储中的数据。如果索引数据使用索引,则需要读取相同的数据

当表增长时,情况(以及EXPLAIN的报告)会发生变化。在某些时候,从索引中读取信息(并使用它来过滤掉行)会被过滤掉的大量行补偿(即不从存储中读取数据)。

发生这种情况时的确切点并不固定。它取决于表的很多结构以及表中的值是如何分散的。即使表很大,MySQL也可以决定忽略索引,以便从存储介质中读取更少的信息。例如,如果表行的大部分(比如90%)与WHERE条件匹配,则读取所有表数据(并忽略索引)比读取90%的表数据更有效和指数的90%。

前一段中的90%是我为解释目的而编写的数字。我不知道MySQL如何决定忽略索引更好。