简体   繁体   English

查询“IS NULL”时,为什么索引列会慢慢返回结果?

[英]Why would an indexed column return results slowly when querying for `IS NULL`?

I have a table with 25 million rows, indexed appropriately. 我有一个2500万行的表,索引适当。

But adding the clause AND status IS NULL turns a super fast query into a crazy slow query. 但添加子句AND status IS NULL会将超快查询转换为疯狂的慢查询。

Please help me speed it up. 请帮我加快速度。

Query: 查询:

SELECT 
    student_id,
    grade,
    status
FROM 
    grades
WHERE 
        class_id = 1
    AND status IS NULL       -- This line delays results from <200ms to 40-70s!
    AND grade BETWEEN 0 AND 0.7
LIMIT 25;

Table: 表:

CREATE TABLE IF NOT EXISTS `grades` (
  `student_id` BIGINT(20) NOT NULL,
  `class_id` INT(11) NOT NULL,
  `grade` FLOAT(10,6) DEFAULT NULL,
  `status` INT(11) DEFAULT NULL,
  UNIQUE KEY `unique_key` (`student_id`,`class_id`),
  KEY `class_id` (`class_id`),
  KEY `status` (`status`),
  KEY `grade` (`grade`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Local development shows results instantly (<200ms). 本地开发立即显示结果(<200ms)。 Production server is huge slowdown (40-70 seconds!). 生产服务器大幅减速(40-70秒!)。

Can you point me in the right direction to debug? 你能指出我正确的调试方向吗?

Explain: 说明:

+----+-------------+--------+-------------+-----------------------+-----------------+---------+------+-------+--------------------------------------------------------+
| id | select_type | table  | type        | possible_keys         | key             | key_len | ref  | rows  | Extra                                                  |
+----+-------------+--------+-------------+-----------------------+-----------------+---------+------+-------+--------------------------------------------------------+
|  1 | SIMPLE      | grades | index_merge | class_id,status,grade | status,class_id | 5,4     | NULL | 26811 | Using intersect(status,class_id); Using where          |
+----+-------------+--------+-------------+-----------------------+-----------------+---------+------+-------+--------------------------------------------------------+

A SELECT statement can only use one index per table. SELECT语句每个表只能使用一个索引。

Presumably the query before just did a scan using the sole index class_id for your condition class_id=1 . 据推测,之前的查询仅使用条件class_id=1的唯一索引class_id进行扫描。 Which will probably filter your result set nicely before checking the other conditions. 在检查其他条件之前,这可能会很好地过滤您的结果集。

The optimiser is 'incorrectly' choosing an index merge on class_id and status for the second query and checking 26811 rows which is probably not optimal. 优化器“错误地”在class_id上选择索引合并,为第二个查询选择status ,并检查可能不是最佳的26811行。 You could hint at the class_id index by adding USING INDEX (class_id) to the end of the FROM clause. 您可以通过在FROM子句的末尾添加USING INDEX (class_id)来提示class_id索引。 You may get some joy with a composite index on (class_id,status,grade) which may run the query faster as it can match the first two and then range scan the grade . 您可以通过(class_id,status,grade)上的复合索引获得一些乐趣,它可以更快地运行查询,因为它可以匹配前两个,然后范围扫描grade I'm not sure how this works with null though. 我不确定这是如何使用null

I'm guessing the ORDER BY pushed the optimiser to choose the class_id index again and returned your query to it's original speed. 我猜测ORDER BY推动优化器再次选择class_id索引并将查询返回到原始速度。

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

相关问题 查询列的右4时空白结果 - Blank results when querying the right 4 of a column 仅查询索引字段时,在 EXPLAIN 的额外列中获取“Using where; Using index” - Getting "Using where; Using index" in Extra column of EXPLAIN when only querying indexed fields 当对NULL列使用WHERE子句时,mySQL select查询不会返回结果。 - mySQL select query does not return results when using a WHERE clause against a NULL column. 查询时具有auto_increment默认值的列为NULL - Column with auto_increment default value is NULL when querying 为什么 MySQL 会返回 NULL 而字段中有值? - Why would MySQL return NULL yet there is a value in the field? MySQL-为什么对索引列执行的select语句返回索引信息,而不返回列数据? - MySQL - Why does a select statement on an indexed column return the index information, and not the column data? 为什么要在所需的数据库列上设置 `null: false, default: “”`? - Why would you set `null: false, default: “”` on a required DB column? 查询数据库时未显示结果 - No results displayed when querying database 为什么查询优化器会显示扫描的行数 = 匹配行的总数,尽管在应用了限制的索引列上进行过滤? - Why would the query optimiser show rows scanned = total number of matched rows despite filtering on an indexed column with a limit applied? 值为空时查询的问题 - Problems with querying when a value is null
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM