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
包含许多不同的值,请使用它。如果status
或countrycode
包含更多不同的值,请使用其中之一。根据您索引的第一列的具体程度,索引单个列可能就足够了。如果没有,请尝试将具有次佳基数的列添加到索引中,等等。
当然,请记住索引(通常,并非总是)会加快查找速度,但会减慢更新、插入和删除的速度!
所以你看,这不是一个非常简单的问题。还要考虑到我概述的内容只是索引冰山的一角。
来源: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使用主键而不是索引的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 2005 会因为我使用 nvarchar(50) 而不是整数作为主键而惩罚我吗?