这是我的表架构。
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行。
答案 0 :(得分:1)
实际使用了您的索引,请参阅key
列。目前查询看起来很好,执行计划也很好。
使用它至少填充一百(并确保您仍然使用仅过滤一行的谓词)。
一般建议:除非你自己是一个mysql dbms开发人员,否则几乎无法预测优化器在特定情况下的行为。因此,尝试尽可能接近(在数据的大小和质量方面)的数据集总是更好。
答案 1 :(得分:1)
WHERE
子句(usr_uid
和block_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如何决定忽略索引更好。