Mysql 性能不佳查询中的优化
我有下面的查询,它工作正常,但是运行非常糟糕。我怀疑我的问题在于内部JOIN语句中的两个比较条件。这两个字段都有索引,但MySQL中的查询优化程序似乎忽略了它们。我的问题是: 编辑:将查询更改为使用Gordon建议的以下查询,因为它保留了相同的结果,但执行速度更快。EXPLAIN语句仍然不满意,输出如下所示。Mysql 性能不佳查询中的优化,mysql,sql,optimization,Mysql,Sql,Optimization,我有下面的查询,它工作正常,但是运行非常糟糕。我怀疑我的问题在于内部JOIN语句中的两个比较条件。这两个字段都有索引,但MySQL中的查询优化程序似乎忽略了它们。我的问题是: 编辑:将查询更改为使用Gordon建议的以下查询,因为它保留了相同的结果,但执行速度更快。EXPLAIN语句仍然不满意,输出如下所示。 SELECT a.id FROM pc a INNER JOIN (SELECT correction_value, MAX(seenDate) mxdate
SELECT a.id
FROM pc a INNER JOIN
(SELECT correction_value, MAX(seenDate) mxdate
FROM pc FORCE INDEX (IDX_SEENDATE)
WHERE seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value
) b
ON a.correction_value = b.correction_value AND
a.seenDate = b.mxdate INNER JOIN
cameras c
ON c.camera_id = a.camerauid
WHERE c.in_out = 0;
解释
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 2414394 | 100 | Using where; |
| | | | | | | | | | | | Using temporary; |
| | | | | | | | | | | | Using filesort |
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
| 1 | PRIMARY | a | NULL | ref | correction_value, | idx_seenDate | 5 | b.mxdate | 1 | 3.8 | Using where |
| | | | | | idx_seenDate, | | | | | | |
| | | | | | fk_camera_idx | | | | | | |
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
| 1 | PRIMARY | c | NULL | ALL | PRIMARY | NULL | NULL | NULL | 41 | 2.44 | Using where; |
| | | | | | | | | | | | Using join buffer (Block Nested Loop) |
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
| 2 | DERIVED | pc | NULL | range | correction_value, | idx_seenDate | 5 | NULL | 2414394 | 100 | Using index Condition; |
| | | | | | idx_seenDate | | | | | | Using temporary; |
| | | | | | | | | | | | Using filesort |
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
|id |选择|类型|表格|分区|类型|可能的|键|键|列|参考|行|过滤|额外|
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
|1 | PRIMARY | NULL | ALL | NULL | NULL | NULL | NULL | 2414394 | 100 |使用where|
|| | | | | | | | | | | |临时使用|
|| | | | | | | | | | | | |使用文件排序|
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
|1 | PRIMARY | a | NULL | ref | correction |值| idx | u seenDate | 5 | b.mxdate | 1 | 3.8 |使用where|
|| | | | | | | | | | | | | ||
|| | | | | | | | | | | | | ||
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
|1 | PRIMARY | c | NULL | ALL | PRIMARY | NULL | NULL | NULL | 41 | 2.44 |使用where|
|使用连接缓冲区(块嵌套循环)|
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
|2 |使用索引条件导出| pc | NULL |范围|校正|值| idx | U seenDate | 5 | NULL | 2414394 | 100 ||
|| | | | | | | | | | | | | | | | | | |使用临时的|
|| | | | | | | | | | | | |使用文件排序|
+----+-------------+------------+------------+-------+-------------------+--------------+---------+----------+---------+----------+---------------------------------------+
如何优化查询,但仍然有相同的结果?试试这个
SELECT
a.id
FROM pc a
INNER JOIN
(SELECT correction_value, MAX(seenDate) mxdate
FROM pc
INNER JOIN cameras ON (cameras.camera_id = pc.camerauid AND cameras.in_out = 0)
WHERE pc.seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value) b ON (a.correction_value = b.correction_value AND a.seenDate = b.mxdate);
使用pc.seenade列上的索引。我首先将查询写为:
SELECT a.id
FROM pc a INNER JOIN
(SELECT correction_value, MAX(seenDate) mxdate
FROM pc
WHERE seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value
) b
ON a.correction_value = b.correction_value AND
a.seenDate = b.mxdate INNER JOIN
cameras c
ON c.camera_id = a.camerauid
WHERE c.in_out = 0; - don't use single quotes if `in_out` is a number
该查询的起始位置是索引:pc(参见数据,校正值,参见数据)
和摄像机(摄像机id,输入输出)
如果这还不够的话,可能还有重写查询的方法。从您的问题来看,不清楚表是如何索引的,但是在这个子查询中
(SELECT correction_value, MAX(seenDate) mxdate
FROM pc FORCE INDEX (IDX_SEENDATE)
WHERE seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value
) b
您希望在两个字段上都有一个复合索引请参见数据,更正\u值
:
CREATE INDEX seenCorr_ndx ON pc (seenDate, correction_value);
(您可以单独在seenDate
上删除任何索引,我希望您也不需要强制索引)
您可能最终需要两个复合索引,一个先带有
seenDate
,一个先带有correction\u值。RDBMS使用第一个查询的输出作为下一个查询的输入。因此,如果我们查看派生查询,它使用的是一个过滤器,因此我们可以使用它作为第一个查询,然后连接到pc,然后连接到摄像机表
索引:由Gordon Linof或pc(id,校正值,见数据)和摄像头(摄像头id,输入输出)提及
最终查询可以重写如下:
SELECT a.id
--add any other column here, you want to show in the EXPLAINED output
FROM
(
SELECT id, correction_value, MAX(seenDate) mxdate
FROM pc
WHERE seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value
) a
INNER JOIN pc b
ON a.correction_value = b.correction_value
AND a.seenDate = b.mxdate
INNER JOIN cameras c
ON c.camera_id = a.camerauid
WHERE c.in_out = 0;
让我们首先关注子查询
SELECT correction_value,
MAX(seenDate) mxdate
FROM pc
WHERE seenDate BETWEEN '2017-03-01' AND '2017-04-01'
GROUP BY correction_value
请用两次,用两次
INDEX sc (seenDate, correction_value)
INDEX cs (correction_value, seenDate)
请先强制一个索引,然后强制另一个索引。根据您正在运行的MySQL版本,其中一个索引将比另一个更好地工作
我认为以后的版本会更喜欢“cs”,因为它可以非常高效地跨越索引
确定要使用的复合索引后,请删除FORCE
和未使用的索引,然后尝试整个查询。对于组合查询,同样的索引也可以
由于您的任务似乎涉及到“groupwise max”,我建议您看看这里是否有性能提示:in__out列属于哪个表???@AshutoshSIngh-cameras表。但是这是不相关的,因为性能问题是在内部连接条件中。什么列是in\u out
in?@GordonLinoff-cameras表。更新了问题。pc表上的索引是什么?列顺序是什么?你也可以把解释输出放在哪里。索引应该放在哪一部分?我把它放在