有没有办法优化这个查询
Posted
技术标签:
【中文标题】有没有办法优化这个查询【英文标题】:Is there a way to optimize this query 【发布时间】:2019-11-26 18:42:19 【问题描述】:我已经写了一个查询,但它需要很多时间。我想知道是否存在任何解决方案来优化它而不在 mysql 中创建临时表。有没有办法优化子查询部分,因为 AccessLog2019 很大,所以它需要永远)
这是我的查询
SELECT distinct l.ListingID,l.City,l.ListingStatus,l.Price,l.Bedrooms,l.FullBathrooms, gc.Latitude,gc.Longitude , count(distinct s.AccessLogID) AS access_count, s.LBID , lb.CurrentListingID
from lockbox.Listings l
JOIN lockbox.GeoCoordinates gc ON l.ListingID = gc.ID
LEFT JOIN lockbox.LockBox lb ON l.ListingID = lb.CurrentListingID
LEFT JOIN
(SELECT * FROM lockbox.AccessLog2019 ac where ac.AccessType not in('1DayCodeGen','BluCodeGen','SmartMACGen') AND DATEDIFF(NOW(), ac.UTCAccessedDT ) < 1 ) s
ON lb.LBID = s.LBID
WHERE l.AssocID = 'AS00000000CC' AND (gc.Confidence <> '5 - Unmatchable' OR gc.Confidence IS NULL OR gc.Confidence = ' ')
group BY l.ListingID
谢谢
【问题讨论】:
您需要来自AccessLog2019
的*
吗?您还索引了表格吗?
仅供参考,许多 Stack Overflow 回答者甚至不会查看查询优化问题,除非您为查询中的每个表共享 (a) SHOW CREATE TABLE <tablename>\G
的输出,(b) EXPLAIN
对于查询,以及 (c) SHOW TABLE STATUS LIKE '<tablename>'\G
查询中的每个表。
添加到@BillKarwin 的评论,然后我们也可以验证这里是否正确使用了 GROUP BY,这似乎是非标准的(SQL 1992) GROUP BY 用法,并且仅在运行时有效在 MySQL 5.7.5+ 支持的 SQL 1999+ 标准上(启用 ONLY_FULL_GROUP_BY sql_mode)称为functional dependency.. ..
如前所述,您的日期计算不能使用函数,但可以重新排列该部分
要详细说明@PritamBanerjee 的评论,您可能想尝试在 AccessType 上为 table lockbox.AccessLog2019 添加一个索引,以帮助“哪里不在...”
【参考方案1】:
如果你能避开外部的group by
,那就是一个巨大的胜利。我在想:
SELECT l.ListingID, l.City, l.ListingStatus, l.Price, l.Bedrooms, l.FullBathrooms,
gc.Latitude, gc.Longitude,
(select count(*)
from lockbox.LockBox lb join
lockbox.AccessLog2019 ac
on lb.LBID = ac.LBID
where l.ListingID = lb.CurrentListingID and
ac.AccessType not in ('1DayCodeGen', 'BluCodeGen', 'SmartMACGen') and
DATEDIFF(NOW(), ac.UTCAccessedDT) < 1
) as cnt
from lockbox.Listings l JOIN
lockbox.GeoCoordinates gc
ON l.ListingID = gc.ID
WHERE l.AssocID = 'AS00000000CC' AND
(gc.Confidence <> '5 - Unmatchable' OR
gc.Confidence IS NULL OR
gc.Confidence = ' '
)
注意:这不会选择 s.LBID
或 lb.CurrentListingID
,因为它们在您的查询中没有意义。如果我理解正确,这些可能在不同的行上有不同的值。
【讨论】:
【参考方案2】:您可以尝试将子查询拆分为 JOIN 子句。
它可能会向优化器提示它可以先使用 LBID 字段,然后再测试 AccessType(以防优化器在您有子选择时没有弄清楚)。
SELECT distinct l.ListingID,l.City,l.ListingStatus,l.Price,l.Bedrooms,l.FullBathrooms, gc.Latitude,gc.Longitude , count(distinct s.AccessLogID) AS access_count, s.LBID , lb.CurrentListingID
from lockbox.Listings l
JOIN lockbox.GeoCoordinates gc ON l.ListingID = gc.ID
LEFT JOIN lockbox.LockBox lb ON l.ListingID = lb.CurrentListingID
LEFT JOIN AccessLog2019 s
ON lb.LBID = s.LBID
AND s.AccessType not in('1DayCodeGen','BluCodeGen','SmartMACGen')
AND DATEDIFF(NOW(), s.UTCAccessedDT ) < 1
WHERE l.AssocID = 'AS00000000CC' AND (gc.Confidence <> '5 - Unmatchable' OR gc.Confidence IS NULL OR gc.Confidence = ' ')
group BY l.ListingID
请注意,这是 JOIN 子句中的条件给出的行为与使用 WHERE 子句不同的情况之一。如果你只有lb.LBID = s.LBID
,然后有我在外部查询的WHERE
中写的条件,结果会有所不同。他们将排除匹配lb.LBID = s.LBID
的记录。但是在JOIN
子句中,它是外连接条件的一部分。
【讨论】:
这似乎是非标准(SQL 1992)GROUP BY 用法,并且仅在 MySQL 5.7.5+ 支持的 SQL 1999+ 标准上运行时有效(启用 ONLY_FULL_GROUP_BY sql_mode),称为@ 987654321@ ...换句话说,此查询可以给出的结果可能是无效的,因为每个组的不相关值... @RaymondNijland 是的,我注意到 mysql 支持非标准 SQL 功能,即使用主键进行分组,而不列出所有字段。 “是的,我注意到mysql支持一个非标准的SQL特性,即使用主键进行分组” 嗯,函数依赖实际上定义为ANSI/ISO SQL 99 中的>可选功能 ... 不知道 ANSI/ISO SQL 标准是否会更进一步,然后 MySQL 支持在运行时查找功能依赖项(这意味着使用DISTINCT
运行的查询作为简单示例)和不超出唯一表约束而已..【参考方案3】:
SELECT *
--> 只选择需要的列。
SELECT DISTINCT ... GROUP BY
-- 做一个或另一个,而不是两个。
需要复合INDEX(AssocID, ListingID)
(按此顺序)
DATEDIFF(NOW(), ac.UTCAccessedDT ) < 1
--> ac.UTCAccessedDT > NOW() - INTERVAL 1 DAY
(或任何你的意图。然后添加INDEX(UTCAccessedDT)
OR
难以优化;考虑清理数据,使 Confidence
没有 3 个值表示相同的含义。
【讨论】:
以上是关于有没有办法优化这个查询的主要内容,如果未能解决你的问题,请参考以下文章
条件检查之间的Mysql中有多个条件?有没有办法优化这个查询?