为什么mysql(mariadb)使用下面的查询花了3分钟来统计记录?

lkaoscv7  于 2021-06-18  发布在  Mysql
关注(0)|答案(4)|浏览(233)

我在寻找原因和建议。我的表有大约140万行,当我运行下面的查询时,它花费了3分钟。为了显示结果,我加了count。我真正的疑问是不计其数的。

MariaDB [ams]> SELECT count(asin) FROM asins where asins.is_active = 1 
and asins.title is null and asins.updated < '2018-10-28' order by sortorder,id;

+-------------+
| count(asin) |
+-------------+
|      187930 |
+-------------+

1 row in set (3 min 34.34 sec)

结构

id int(9) Primary
asin varchar(25) UNIQUE
is_active int(1) Index 
sortorder int(9) Index

如果你需要更多的信息,请告诉我。提前谢谢。
用explain编辑查询
mariadb[ams]>explain select asin from asins where asins.is_active=1 and asins.title is null and asins.updated<'2018-10-28'order by sortorder,id;

ifmq2ha2

ifmq2ha21#

您的索引似乎处于活动状态并已更新。所以索引将被扫描(就像表扫描一样,索引中的每条记录都被读取),但是由于标题不在索引中,因此将有第二个操作在表中查找标题。您可以将其视为索引和表之间的连接。如果索引中的大多数记录都符合您的条件,那么连接将涉及表中的大部分数据。大连接速度慢。
如果针对索引的条件将导致返回大量记录,则最好进行全表扫描。
看到了吗https://dba.stackexchange.com/questions/110707/how-can-i-force-mysql-to-ignore-all-indexes 一种强制全表扫描的方法。试试看你的查询速度是否更快。

ix0qys7i

ix0qys7i2#

数据库正在扫描所有行以回答查询。我想你有一张很大的table。
对于此查询 ORDER BY 不必要(但不应影响性能:

SELECT count(asin)
FROM asins 
WHERE asins.is_active = 1 AND
      asins.title is null AND
      asins.updated < '2018-10-28' ;

然后你需要一个索引 (is_active, title, updated) .

6l7fqoea

6l7fqoea3#

创建复合索引时,如果其中一部分是基于范围的,则首先需要基于范围的部分。
因此,请尝试索引(已更新,是否处于活动状态,标题)
这种方式更新成为前缀,可以在范围查询中使用。

oalqel3c

oalqel3c4#

试试这些:

INDEX(is_active, updated),
INDEX(is_active, sortorder, id)

请提供 SHOW CREATE TABLE .
对于这些索引中的第一个,将进行一些筛选,但之后仍需对结果进行排序。
对于第二个索引,优化器可以选择只在 = 列,然后通过启动 ORDER BY . 风险在于,它仍将遭遇如此多的争吵,以至于避免这样的争吵是不值得的。
表中有多少百分比 is_active = 1 ? 什么百分比有空值 title ? 那个日期范围内的百分比是多少?

相关问题