我的查询在我们的服务器上耗时17-20秒,我想看看我能做些什么来对其进行优化。 MySQL 5.6,将在接下来的几个月中升级到5.7。
查询:
SELECT pm.mid AS mid
FROM
pm_message pm
INNER JOIN pm_index pmi ON pmi.mid = pm.mid
GROUP BY pm.mid
HAVING (MIN(pmi.deleted) > 0 AND MAX(pmi.deleted) < '1535490002')
LIMIT 1000 OFFSET 0;
pm_message和pm_index中的中间列都是两个表中的主键。 该表每个都有数百万条记录
select count(*) from pm_message;
3748290
select count(*) from pm_index;
6938947
对改进此查询有何建议?
我想知道是否将pm_index表中的'deleted'列用作索引会有所帮助?
答案 0 :(得分:1)
我将完全重写查询,因为您基本上想要一个列表,这些列表中删除的范围在一定范围内。您不需要显示pm_index
表中的任何数据,因此我将使用关联的子查询与not exists
运算符。这样,mysql不必对整个pm_index
表进行分组和排序即可获得最小值和最大值。
SELECT pm.mid AS mid
FROM
pm_message pm
WHERE NOT EXISTS (SELECT 1 FROM pm_index WHERE pm_index.mid=pm.mid and (pm_index.deleted<0 OR pm_index.deleted>1535490002))
该查询将受益于pm_index
表的中间和已删除字段上的多列索引。
答案 1 :(得分:1)
这详细说明了Shadows的答案。尝试使用两个$scope.retrieveSelectedClass = function(newValue, oldValue, event) {
}
子句:
not exists
并确保您在SELECT pm.mid
FROM pm_message pm
WHERE NOT EXISTS (SELECT 1
FROM pm_index pmi
WHERE pmi.mid = pm.mid AND
pmi.deleted < 0
) AND
NOT EXISTS (SELECT 1
FROM pm_index pmi
WHERE pmi.mid = pm.mid AND
pmi.deleted > 1535490002
) ;
上有一个索引。该索引非常重要。我将其分为两个子句,因为pm_index(mid, deleted)
会混淆查询优化器。
答案 2 :(得分:0)
尝试一下。它可以将事情彻底解决-从pmi开始,然后最大程度地减少对pm的接触。
SELECT mid, MIN(deleted) AS mind, MAX(deleted) AS maxd
FROM pm_index AS pmi
GROUP BY mid
HAVING mind > 0
AND maxd < '1535490002'
AND EXISTS (
SELECT 1
FROM pm
WHERE mid = pmi.mid
)
LIMIT 1000 OFFSET 0;
我怀疑这是否会有帮助-查询似乎需要触摸两个表中的几乎所有行。
如果pmi中的 all 所有mid
值确实存在于pm
中,则可以删除我的EXISTS
子句。但是,您说两个表都有PRIMARY KEY(mid)
吗?我怀疑pmi
的PK中实际上还有第二列。 请提供SHOW CREATE TABLE
。