Rya*_*yan 7 mysql sql optimization null query-optimization
我有一个2500万行的表,索引适当.
但添加该子句AND status IS NULL会将超快速查询转换为疯狂的慢查询.
请帮我加快速度.
查询:
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;
Run Code Online (Sandbox Code Playgroud)
表:
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;
Run Code Online (Sandbox Code Playgroud)
本地开发立即显示结果(<200ms).生产服务器大幅减速(40-70秒!).
你能指出我正确的调试方向吗?
说明:
+----+-------------+--------+-------------+-----------------------+-----------------+---------+------+-------+--------------------------------------------------------+
| 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 |
+----+-------------+--------+-------------+-----------------------+-----------------+---------+------+-------+--------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
一条SELECT语句每个表只能使用一个索引。
大概之前的查询只是使用class_id您的条件的唯一索引进行了扫描class_id=1。在检查其他条件之前,这可能会很好地过滤您的结果集。
优化器“错误地”为第二个查询选择索引合并class_id并status检查 26811 行,这可能不是最佳的。class_id您可以通过添加到子句USING INDEX (class_id)末尾来暗示索引FROM。您可能会对复合索引感到高兴,复合索引(class_id,status,grade)可以更快地运行查询,因为它可以匹配前两个索引,然后对grade. 我不确定这是如何运作的null。
我猜想ORDER BY推动优化器再次选择class_id索引并将您的查询返回到原始速度。
| 归档时间: |
|
| 查看次数: |
66 次 |
| 最近记录: |