mysql使用主键而不是索引

Posted

技术标签:

【中文标题】mysql使用主键而不是索引【英文标题】:mysql uses primary key instead of index 【发布时间】:2013-08-10 13:00:06 【问题描述】:

我有一个相当大的表,有几百万行:

ID (primary)
countrycode
status
flag_cc

我试过下面的sql语句,但是很慢:

SELECT id, countrycode, status, flag_cc FROM table WHERE ID>=200000 AND countrycode=3 AND status=1 AND flag_cc=0

所以我认为添加索引来固定查询是个好主意:

ADD INDEX myindex(id, countrycode, status, flag_cc)

然后我查询:

EXPLAIN SELECT id, countrycode, status, flag_cc FROM table WHERE ID>=200000 AND countrycode=3 AND status=1 AND flag_cc=0

但是mysql想要使用主键而不是我的键。所以我使用了 FORCE INDEX 并将主键与我的键进行了比较。遗憾的是主键要快得多。

怎么可能?如果主键太慢,是否有可能优化该查询?

【问题讨论】:

尝试添加一个没有主键或 3 个单独键的复合键。 如果我添加一个没有主键的复合键,它仍然会使用主键.. 按该顺序尝试索引 (countrycode, status, flag_cc, id)。先找到常量可能会更快。 【参考方案1】:

您的问题基本上是“什么是好的索引?”。您可能需要考虑在 MySQL 文档、*** 上以及使用任何搜索引擎来阅读它们。

考虑一个类似于大百科全书索引的索引。定义了很多主题,因此索引可以帮助您更快地找到所需内容。

但是索引中应该包含什么?类别(科学、娱乐、人物……)?然后,当您找到该类别时,仍然有很多文章属于每个类别。假设共有 10 000 篇文章,其中 1000 篇属于科学类别。如果你正在寻找一些科学的东西,那仍然会给你留下 1000 篇文章来寻找你的确切文章。在数据库方面,这个索引没有很好的基数:如果你没有其他东西但不够具体以真正加快速度,那就太好了。这同样适用于以起始字母开头的索引(字母表中有 26 个字母,因此使用索引将要查找的文章数除以大约 26,这也不是很具体)。

在数据库中,这意味着主键是一个非常好的索引字段:该字段的一个值对应于数据中的一个值,因此一旦使用索引找到它,就没有什么可看的了;你已经找到了具体的记录。

另一方面,真/假标志仅将您的数据分成最多两组,因此即使在使用索引后仍然留下大量数据可供查看。

当然,也有例外。例如,具有真/假列的表。通常这是一个不好索引的列。但是您可能知道所有记录中只有 0.01% 的该列的值为“true”,并且您的查询查找的是真实值,而不是虚假值。在这种情况下,该真/假列是一个很好的索引列。

然后是范围问题:您不是在搜索特定 ID,而是在搜索它们的整个范围,因此即使 ID 是唯一的,它仍然会标记索引的整个部分(以及数据)作为“使用索引后仍需查看的内容”。因此,虽然它具有良好的 基数,但它可能不是用于此特定查询的最佳索引。

另一个问题是,当您不在索引的第一列上搜索时,MySQL 无法查看多列索引。所以一个索引(ID、countrycode、status、flag_cc)意味着 MySQL 仍然必须按 ID 开始使用索引,这在您的查询中是一个范围条件,上一段解释了为什么这样做不好。只有在应用了索引的 ID 部分之后,它才能从 countrycode 部分开始,如果 MySQL 确定这仍然值得努力的话。这可能就是 MySQL 想要使用您的主键索引的原因,即使您已经给了它另一个选项。

在您的表上应用所有这些信息:您的 where 子句包含所有列,因此从具有最高基数(最不同的值)的列开始构建索引并且不用作范围 where 子句(所以不ID)。如果flag_cc 包含许多不同的值,请使用它。如果statuscountrycode 包含更多不同的值,请使用其中之一。根据您索引的第一列的具体程度,索引单个列可能就足够了。如果没有,请尝试将具有次佳基数的列添加到索引中,等等。

当然,请记住索引(通常,并非总是)会加快查找速度,但会减慢更新、插入和删除的速度!

所以你看,这不是一个非常简单的问题。还要考虑到我概述的内容只是索引冰山的一角。

来源:http://webmonkeyuk.wordpress.com/2010/09/27/what-makes-a-good-mysql-index-part-2-cardinality/https://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html

【讨论】:

以上是关于mysql使用主键而不是索引的主要内容,如果未能解决你的问题,请参考以下文章

如何使用唯一键而不是主键在 Hibernate 中检索记录

SQL Server 2005 会因为我使用 nvarchar(50) 而不是整数作为主键而惩罚我吗?

在sqlite中插入时获取主键而不是rowID或通过其rowID获取主键

Postgres 更新不使用主键索引

使用亚马逊管道的红移副本因缺少主键而失败

主键是不是在 MySQL 中自动建立索引?