您的问题基本上是“什么是好的索引?”。您可能需要考虑在 MySQL 文档中、在 stackoverflow 上以及使用任何搜索引擎来阅读它们。
考虑一个类似于大百科全书中的索引的索引。定义了很多主题,因此索引可以帮助您更快地找到所需内容。
但索引中应该包含什么?类别(科学、娱乐、人物……)?然后,当您找到该类别时,每个类别中仍然有大量文章。假设总共有 10 000 篇文章,其中 1000 篇属于科学类别。如果您正在寻找一些科学的东西,那么您仍然可以找到 1000 篇文章来查找您的确切文章。用数据库术语来说,该索引没有良好的基数:如果您没有其他任何东西但不够具体以真正加快速度,那就太好了。对于以字母开头的索引(字母表中的 26 个字母,因此使用索引,您可以将要查找的文章数量除以大约 26,这也不是很具体),情况也是如此。
在数据库中,这意味着主键是一个非常适合建立索引的字段:该字段的一个值恰好对应于数据中的一个值,因此一旦使用索引来查找它,就没有什么可查找的了;您已经找到了具体记录。
另一方面,真/假标志仅将数据最多分为两组,因此即使在使用索引后仍然留下大量数据可供查看。
当然也有例外。例如,具有真/假列的表。通常这是一个不好的索引列。但您可能知道所有记录中只有 0.01% 的该列值为“true”,并且您的查询查找的是真值,而不是假值。在这种情况下,该真/假列是一个很好的索引列。
然后是范围问题:您不是在搜索特定的 ID,而是搜索它们的整个范围,因此即使 ID 是唯一的,它仍然会将索引的整个部分(以及数据)标记为“事物”使用索引后仍然可以查看'。因此,虽然它具有良好的基数,但它可能不是用于此特定查询的最佳索引。
另一个问题是,当您不搜索索引的第一列时,MySQL 无法查看多列索引。因此,索引(ID、国家/地区代码、状态、flag_cc)意味着 MySQL 仍然必须开始使用 ID 索引,这在查询中是范围条件,上一段解释了为什么这样做不好。只有在应用了索引的 ID 部分之后,如果 MySQL 确定这仍然值得付出努力,它才能从国家/地区代码部分开始。这可能就是为什么 MySQL 想要使用你的主键索引,即使你已经给了它另一个选项。
将所有这些信息应用到您的表上:您的 where 子句包含所有列,因此从基数最高(最不同的值)的列开始构建索引,并且该索引不用作范围 where 子句(因此不ID
). If flag_cc
包含很多不同的值,请使用它。如果status
or countrycode
包含更多不同的值,请使用其中之一。根据您索引的第一列的具体程度,对单个列进行索引可能就足够了。如果没有,请尝试将具有次佳基数的列添加到索引中,等等。
当然,请记住索引(通常但并非总是)可以加快查找速度,但会减慢更新、插入和删除速度!
所以你看,这不是一个很简单的问题。还要考虑到我概述的内容只是索引冰山一角。
Sources:
http://webmonkeyuk.wordpress.com/2010/09/27/what-makes-a-good-mysql-index-part-2-cardinality/ 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 https://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html