【发布时间】:2015-08-02 18:00:54
【问题描述】:
我有一个 SQL 请求,它在工作时占用了我的 VM CPU 的 100%。我想知道如何优化它:
SELECT g.name AS hostgroup
, h.name AS hostname
, a.host_id
, s.display_name AS servicename
, a.service_id
, a.entry_time AS ack_time
, ( SELECT ctime
FROM logs
WHERE logs.host_id = a.host_id
AND logs.service_id = a.service_id
AND logs.ctime < a.entry_time
AND logs.status IN (1, 2, 3)
AND logs.type = 1
ORDER BY logs.log_id DESC
LIMIT 1) AS start_time
, ar.acl_res_name AS timeperiod
, a.state AS state
, a.author
, a.acknowledgement_id AS ack_id
FROM centstorage.acknowledgements a
LEFT JOIN centstorage.hosts h ON a.host_id = h.host_id
LEFT JOIN centstorage.services s ON a.service_id = s.service_id
LEFT JOIN centstorage.hosts_hostgroups p ON a.host_id = p.host_id
LEFT JOIN centstorage.hostgroups g ON g.hostgroup_id = p.hostgroup_id
LEFT JOIN centreon.hostgroup_relation hg ON a.host_id = hg.host_host_id
LEFT JOIN centreon.acl_resources_hg_relations hh ON hg.hostgroup_hg_id = hh.hg_hg_id
LEFT JOIN centreon.acl_resources ar ON hh.acl_res_id = ar.acl_res_id
WHERE ar.acl_res_name != 'All Resources'
AND YEAR(FROM_UNIXTIME( a.entry_time )) = YEAR(CURDATE())
AND MONTH(FROM_UNIXTIME( a.entry_time )) = MONTH(CURDATE())
AND a.service_id is not null
ORDER BY a.acknowledgement_id ASC
问题出在这部分:
(SELECT ctime FROM logs
WHERE logs.host_id = a.host_id
AND logs.service_id = a.service_id
AND logs.ctime < a.entry_time
AND logs.status IN (1, 2, 3)
AND logs.type = 1
ORDER BY logs.log_id DESC
LIMIT 1) AS start_time
表日志真的很大,一些朋友告诉我使用缓冲表/数据库,但我很了解这些事情,我不知道该怎么做。
查询有一个 EXPLAIN EXTENDED :
看来他只会检查表日志的 2 行,为什么要花这么多时间? (表日志中有 560000 行)。
这是这些表的所有索引:
centstorage.acknowledgements:
centstorage.hosts:
centstorage.services:
centstorage.hosts_hostgroups :
centstorage.hostgroups :
centeron.hostgroup_relation :
centeron.acl_resources_hg_relations:
centeron.acl_resources:
【问题讨论】:
-
哪个 dbms 产品?表和索引定义等
-
首先检查执行计划并验证是否缺少索引。
-
他们都需要
LEFT JOINS吗?表是否充分索引? -
子查询是性能杀手,您应该尝试使用派生表。
-
附注:为什么不希望查询尽可能多地占用 CPU?与“哦,让我们用 10% 的 CPU 运行这个查询,它会花费 10 倍的时间”相比,这肯定是可取的?
标签: mysql sql optimization