mysql - 在可以而且应该使用的地方没有使用索引

标签 mysql database indexing

我有一个(大)表,我使用 WHERE 中的 3 个字段进行查询。其中一个字段有一个索引(日期),我正在寻找过去 3 个月内的点击次数。虽然它永远不会是一个快速查询,但我至少希望使用该日期的索引。

这是我的查询:

SELECT id
FROM statsTable
WHERE 1
   AND ip            =  'ipgoeshere'
   AND anotherstring =  'Quite a long string goes here, something like this or even longer'
   AND `date`        >  DATE_ADD( NOW( ) , INTERVAL -3 MONTH ) 

解释一下:

id  select_type table       type    possible_keys   key     key_len ref     rows    Extra
1   SIMPLE      statsTable  ALL     date            NULL    NULL    NULL    4833721 Using where; Using filesort   

这是一个完整的表扫描,行数是关闭的,因为我猜是 INNODB 行计数,但这就是全部。 这大约需要 30 秒。

如果我像这样强制索引,我会得到预期的结果:

SELECT id
FROM statsTable FORCE INDEX (date)
WHERE 1
   AND ip            =  'ipgoeshere'
   AND anotherstring =  'Quite a long string goes here, something like this or even longer'
   AND `date`        >  DATE_ADD( NOW( ) , INTERVAL -3 MONTH ) 

再次解释一下:

id  select_type table       type    possible_keys   key     key_len ref     rows    Extra
1   SIMPLE      statsTable  range   date            date    8       NULL    1120172 Using where

现在我们“仅”有 100 万个结果,但完成速度“非常快”(例如,3 秒而不是 30 秒)。

表格:

CREATE TABLE IF NOT EXISTS `statsTable` (

  `id`            int(11) unsigned NOT NULL AUTO_INCREMENT,
  `date`          datetime NOT NULL,
  `ip`            varchar(15) NOT NULL,
  `anotherstring` varchar(255) NOT NULL,

  PRIMARY KEY (`id`),
  KEY `date` (`date`)

) ENGINE=InnoDB;

奇怪的是:我也有这个表在另一个数据库上运行(在不同的服务器上运行),并且索引正在该实例中使用。我看不出这里可能有什么问题。是否有我错过的设置?或者可能是其他一些细微的差别?除了差异之外,我不明白为什么上面的查询不使用该 key 。

我已经运行了OPTIMIZE TABLE,并且正如@DhruvPathak建议的ANALYZE TABLE,但解释仍然保持不变。我还根据 friend 的建议尝试了 ALTER TABLE 来重建索引。运气不好。

最佳答案

未使用索引,因为执行计划程序决定最好完全扫描表而不是使用索引。当索引对于查询来说选择性不够时,就会发生这种情况。

如果范围检查中的日期超过整个表的 10-20%,则规划器会决定扫描(顺序)整个表比使用索引并检索属于该范围的行更快(此检索不会按顺序进行,因为行将分散在整个表中)。

这就是为什么您会在不同的数据集上看到不同的行为。


为了让您的查询发挥最佳效果,您可以在以下位置创建索引:

(ip, yourDateField)

(anotherstring, yourDateField)

(ip, anotherstring, yourDateField)

我认为第一个选项的选择性就足够了。无需在索引中添加长 VARCHAR(255) 字段。或者,使用似乎适合您的情况的 FORCE INDEX

关于mysql - 在可以而且应该使用的地方没有使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7266876/

相关文章:

database - 使用扇出写入方法根据隐私设置(PostgreSQL、Redis)更新 Feed

mysql - 当我使用 >= 或 <= 时,我可以在日期字段上放置 mysql 索引吗?

MySql 索引在范围扫描中的工作方式不同

seo - 防止在没有 JavaScript 的情况下阅读和跟踪来自 Google 的 div

具有 50+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?

mysql - MySQL 中 VARCHAR 字段的数值计算

MySQL 仅限日期时间到月份

ruby - Datamapper,定义自己的对象方法,怎么样?

Javascript 不从数据库添加变量

php - 数据库设计缺陷?