【问题标题】:MariaDB SELECT with index used but looks like table scanMariaDB SELECT 使用了索引,但看起来像表扫描
【发布时间】:2020-07-07 21:36:08
【问题描述】:

我有一个 MariaDB 10.4,带有一个挂表(大约 1 亿行),用于存储抓取的帖子。该表包含 4x 列,其中之一是 lastUpadate(日期时间)并被索引。

最近我尝试通过 lastUpdate 选择帖子。它们中的大多数在使用索引的情况下快速返回,但有些需要几分钟,返回的记录较少,看起来像表扫描。

这是不带条件的查询解释。

> explain select 1 from SourceAttr;
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+-------------+
| id   | select_type | table      | type  | possible_keys | key           | key_len | ref  | rows     | Extra       |
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+-------------+
|    1 | SIMPLE      | SourceAttr | index | NULL          | idxCreateDate | 5       | NULL | 79830491 | Using index |
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+-------------+

这是查询解释和慢速返回的行数。解释中rows的数量和上面的差不多。

> select 1 from SourceAttr where (lastUpdate >= '2020-01-11 11:46:37' AND lastUpdate < '2020-01-12 11:46:37');
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+--------------------------+
| id   | select_type | table      | type  | possible_keys | key           | key_len | ref  | rows     | Extra                    |
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+--------------------------+
|    1 | SIMPLE      | SourceAttr | index | idxLastUpdate | idxLastUpdate | 5       | NULL | 79827437 | Using where; Using index |
+------+-------------+------------+-------+---------------+---------------+---------+------+----------+--------------------------+

> select 1 from SourceAttr where (lastUpdate >= '2020-01-11 11:46:37' AND lastUpdate < '2020-01-12 11:46:37');
394454 rows in set (14 min 40.908 sec)

这是最快的。

> explain select 1 from SourceAttr where (lastUpdate >= '2020-01-15 11:46:37' AND lastUpdate < '2020-01-16 11:46:37');
+------+-------------+------------+-------+---------------+---------------+---------+------+---------+--------------------------+
| id   | select_type | table      | type  | possible_keys | key           | key_len | ref  | rows    | Extra                    |
+------+-------------+------------+-------+---------------+---------------+---------+------+---------+--------------------------+
|    1 | SIMPLE      | SourceAttr | range | idxLastUpdate | idxLastUpdate | 5       | NULL | 3699041 | Using where; Using index |
+------+-------------+------------+-------+---------------+---------------+---------+------+---------+--------------------------+

> select 1 from SourceAttr where (lastUpdate >= '2020-01-15 11:46:37' AND lastUpdate < '2020-01-16 11:46:37');
1352552 rows in set (2.982 sec)

有什么原因可能导致这种情况?

非常感谢。

【问题讨论】:

  • 为什么它会选择index作为一个查询,而range作为另一个查询呢?那很奇怪。你能用BETWEEN而不是两个比较和AND来检查吗?
  • @Zrin 没有任何改变。
  • 如果你在最后一个查询中缩小时间范围会发生什么,例如select 1 from SourceAttr where (lastUpdate &gt;= '2020-01-15 11:46:37' AND lastUpdate &lt; '2020-01-15 23:46:37')

标签: mysql mariadb


【解决方案1】:

当您看到type: index 时,这称为索引扫描。这几乎和表扫描一样糟糕。

注意两个慢查询的 EXPLAIN 中的 rows: 79827437。这意味着它正在检查扫描索引中的超过 7900 万个项目,idxCreateDateidxLastUpdate。所以它基本上是检查每个索引条目,这几乎与检查表的每一行所花费的时间一样长。

而快速查询显示rows: 3699041,因此它估计检查的行数少于 370 万行。减少 20 倍以上。

【讨论】:

  • 感谢您的提示。我想念type: index。有什么理由为什么慢查询返回较少的行 type: index 而快速查询返回更多行 type: range
  • 它们是不同的查询,搜索不同时间范围内的行。是不是预计它们会有不同的结果集?
  • @BillKarwin,预计/不清楚它们将以不同的方式执行,优化器会因为常量不同而对它们进行不同的处理。
  • 但是你问他们为什么返回不同的行数。这与优化器的选择无关,它与表中有多少行匹配两个不同的日期范围有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
相关资源
最近更新 更多