为什么MySQL(MariaDB)花费3分钟以上的时间使用以下查询对记录进行计数?

时间:2018-10-28 15:53:13

标签: mysql sql mariadb

我正在寻找原因和建议。 我的表大约有140万行,当我在查询后运行时,花了3分钟以上。我添加计数只是为了显示结果。我真正的查询是数不清的。

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]>从asins中解释asin,其中asins.is_active = 1且asins.title为null且asins.updated <'2018-10-28'按sortorder,id;

enter image description here

4 个答案:

答案 0 :(得分:2)

数据库正在扫描所有行以回答查询。我想你的桌子很大。

对于此查询,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)上建立索引。

答案 1 :(得分:1)

好像您在is_active上有一个索引并已更新。因此将要扫描该索引(就像表扫描一样,读取索引中的每个记录),但是由于title不在索引中,因此将有第二个操作在表中查找title。您可以将其视为索引和表之间的联接。如果索引中的大多数记录都符合您的条件,则联接将涉及表中的大多数数据。大型联接很慢。

如果针对索引的条件将导致返回大量记录,那么使用全表扫描可能会更好。

有关强制全表扫描的方法,请参见https://dba.stackexchange.com/questions/110707/how-can-i-force-mysql-to-ignore-all-indexes。尝试一下,看看您的查询是否更快。

答案 2 :(得分:1)

尝试以下方法:

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

请提供SHOW CREATE TABLE

使用这些索引中的第一个,将完成一些过滤,但是随后仍然需要对结果进行排序。

使用第二个索引,优化器可以选择对唯一的=列进行过滤,然后通过启动ORDER BY来避免排序。这样做的风险是,它仍然必须行很多行,以至于避免进行排序是不值得的。

is_active = 1占表的百分之几?空title为空的百分比是多少?该日期范围内的百分比是多少?

答案 3 :(得分:0)

创建复合索引时,其中一部分是基于范围的,则需要首先基于范围的部分。

所以尝试索引(已更新,is_active,标题)

这种更新方式成为前缀,可以在范围查询中使用。