简体   繁体   English

为什么在较少 char 值上过滤的索引 mysql 查询会导致检查更多行?

[英]Why does an indexed mysql query filtered on less char values result in more rows examined?

When I run the following query, I see the expected rows examined as 40当我运行以下查询时,我看到预期的行检查为 40

EXPLAIN SELECT s.* FROM subscription s
WHERE s.current_period_end_date <= NOW()
AND s.status in ('A', 'T')
AND s.period_end_action in ('R','C')
ORDER BY s._id ASC limit 20;

+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys                  | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | s     | index | status,current_period_end_date | PRIMARY | 4       | NULL |   40 | Using where |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+

But when I run this query that simply changes AND s.period_end_action in ('R','C') to AND s.period_end_action = 'C' , I see the expected rows examined as 611但是,当我运行此查询时,只需将AND s.period_end_action in ('R','C')更改为AND s.period_end_action = 'C' ,我看到预期的行检查为 611

EXPLAIN SELECT s.* FROM subscription s
WHERE s.current_period_end_date <= NOW()
AND s.status in ('A', 'T')
AND s.period_end_action = 'C'
ORDER BY s._id ASC limit 20;

+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys                  | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | s     | index | status,current_period_end_date | PRIMARY | 4       | NULL |  611 | Using where |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+

I have the following indexes on the subscription table:我在订阅表上有以下索引:

_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
INDEX(status, period_end_action),
INDEX(current_period_end_date),

Any ideas?有任何想法吗? I don't understand why removing one of the period_end_action values would cause such a large increase in rows examined?我不明白为什么删除 period_end_action 值之一会导致检查的行数大幅增加?

(I agree with others that EXPLAIN often has terrible row estimates.) (我同意其他人的观点,即EXPLAIN经常有糟糕的行估计。)

Actually the numbers might be reasonable (though I doubt it).实际上这些数字可能是合理的(尽管我对此表示怀疑)。 The optimizer decided to do a table scan in both cases.优化器决定在这两种情况下都进行表扫描。 And the query with fewer options for period_end_action probably has to scan farther to get the 20 rows.并且period_end_action选项较少的查询可能必须扫描更远才能获得 20 行。 This is because it punted on using either of your secondary indexes.这是因为它强调使用您的任何一个二级索引。

These indexes are more likely to help your second query:这些索引更有可能帮助您进行第二次查询:

INDEX(period_end_action, _id)
INDEX(period_end_action, status)
INDEX(period_end_action, current_period_end_date)

The optimal index is usually starts with any columns tested by = .最佳索引通常=测试的任何列开始。

Since there is no such thing for your first query, the Optimizer probably decided to scan in _id order so that it could avoid the "sort" mandated by ORDER BY .由于您的第一个查询没有这样的事情,优化器可能决定按_id顺序扫描,这样它就可以避免ORDER BY规定的“排序”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM