Mysql 性能不佳查询中的优化

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

我有下面的查询,它工作正常,但是运行非常糟糕。我怀疑我的问题在于内部JOIN语句中的两个比较条件。这两个字段都有索引,但MySQL中的查询优化程序似乎忽略了它们。我的问题是:

编辑:将查询更改为使用Gordon建议的以下查询,因为它保留了相同的结果,但执行速度更快。EXPLAIN语句仍然不满意,输出如下所示。

    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表上的索引是什么?列顺序是什么?你也可以把解释输出放在哪里。索引应该放在哪一部分?我把它放在