您的问题基本上是“什么是好的索引?”。您可能需要考虑在 MySQL 文档中阅读它们,这里是 stackoverflow 并且只需使用任何搜索引擎。
考虑一个类似大百科全书索引的索引。定义了很多主题,因此索引可以帮助您更快地找到您正在寻找的内容。
但是索引中应该包含什么?类别(科学、娱乐、人物……)?然后,当您找到该类别时,仍然有很多文章属于每个类别。假设共有 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 子句(因此 not 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