2017-10-11 114 views
0

这是我的表架构。它为什么包含“使用哪里”?

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' 

顺便说一句,当我跑 “解释”,我得到的结果如下。

+------+-------------+-------+------+-----------------------------------------+---------------------+---------+-------------+------+--------------------------+ 
| 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行。

+1

该表中有多少行? – zerkms

+0

1排。索引是不需要的。 –

+3

所以填写一百万行并检查。性能优化不会扩展:您必须专门检查每个案例。 – zerkms

回答

1

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

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

还有一个一般性建议:除非你自己是一个MySQL DBMS开发人员,否则几乎不可能预测优化器在特定情况下的表现。所以最好尝试一种尽可能接近您的产品的数据集(就数据的大小和质量而言)。

+0

我插入了20000行,我试了一下。但我只能得到相同的结果。 –

+0

“但我得到的结果相同”---这是什么意思? – zerkms

+0

'explain'的结果仍然包含“使用where”,尽管此表有20000行。 –

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如何决定忽略索引更好。

+0

谢谢,但这张桌子现在有20000行。 –

+0

@Star_Man ...并使用索引。 – zerkms

相关问题