有没有一种方法可以优化此查询

时间:2019-11-26 18:42:19

标签: mysql sql database query-optimization mysql-workbench

我写了一个查询,但是要花很多时间。我想知道是否存在无需在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

谢谢

3 个答案:

答案 0 :(得分:2)

如果您可以避免使用外部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.LBIDlb.CurrentListingID,因为它们在您的查询中没有意义。如果我理解正确,那么它们在不同的行上可能具有不同的值。

答案 1 :(得分:1)

您可以尝试将子查询分解为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子句中,它是外部联接条件的一部分。

答案 2 :(得分:1)

  • SELECT *->仅选择所需的列。
  • SELECT DISTINCT ... GROUP BY-只能做一个或一个,不要两个都做。
  • 需要复合INDEX(AssocID, ListingID)(按此顺序)
  • DATEDIFF(NOW(), ac.UTCAccessedDT ) < 1-> ac.UTCAccessedDT > NOW() - INTERVAL 1 DAY(或您的意图是什么。然后添加INDEX(UTCAccessedDT)
  • OR难以优化;考虑清理数据,以使Confidence的3个值相同。