为什么这个查询在mysql中变慢

时间:2019-05-07 15:16:50

标签: mysql performance

我尝试改善此查询,但未成功完成。我使用一些左联接和子查询(我不知道另一种形式)我们尝试从具有特定状态的用户以及与该预订相关的预订数量的倍数中获取所有预订,并从日志用户那里获取来源。即使使用限制提示,查询也很慢。我感谢您能提供的所有帮助。

这是查询:

SELECT DISTINCT b.uneaque_id, b.id, b.status, b.route_status, b.username, b.purpose, b.transfer, b.pickup_date, b.pickup_time, b.return_time, b.amount, b.default_location, b.start_address_route_comments, b.start_address_route, b.end_address_route_comments, b.end_address_route, u1.first_name, u1.last_name, b.transaction_Id, b.manual_payment, mr.AddressCount, lu.origin 
        FROM bookingdetails b 
        LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING' 
        LEFT JOIN ( 
            SELECT booking_id, COUNT(*) AS AddressCount FROM booking_multiple_rides GROUP BY booking_id
        ) mr ON b.id = mr.booking_id,
        userdetails u1 WHERE b.username = u1.email 
        AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
        AND b.default_location = 1

PD:对不起,我的英语。

2 个答案:

答案 0 :(得分:0)

您的b.id = mr.booking_id为ON,用户在u1处查看详细信息
您应该使用适当的内部联接进行更改

SELECT DISTINCT b.uneaque_id
    , b.id, b.status
    , b.route_status
    , b.username
    , b.purpose
    , b.transfer
    , b.pickup_date
    , b.pickup_time
    , b.return_time
    , b.amount
    , b.default_location
    , b.start_address_route_comments
    , b.start_address_route
    , b.end_address_route_comments
    , b.end_address_route
    , u1.first_name
    , u1.last_name
    , b.transaction_Id
    , b.manual_payment
    , mr.AddressCount
    , lu.origin 
FROM bookingdetails b 
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING' 
LEFT JOIN ( 
        SELECT booking_id
          , COUNT(*) AS AddressCount 
          FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id
INNER JOIN userdetails u1 ON  b.username = u1.email 
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1

并确保您在上具有正确的索引
表格预订详细说明了列的综合索引(uneaque_id,id,default_location)

表log_users在列上的组合索引(uneaque_id,command_type) 表userdetails在列(email,user_status)上的cmposite索引

答案 1 :(得分:0)

提示1。

LEFT JOIN中隐藏派生表是缓慢的处方。

替换

mr.AddressCount

使用

( SELECT  COUNT(*)
            FROM  booking_multiple_rides
            WHERE booking_id = b.id
            GROUP BY  booking_id ) AS AddressCount

并摆脱LEFT JOIN ( SELECT ... ) AS mr ON ..

技巧2使用显式JOINs,不要使用老式的“逗号联接”:

JOiN userdetails u1
    ON  b.username = u1.email

这对性能没有帮助,但是会使情况变得更清楚。

提示3:如果在INNER JOIN之后需要LEFT JOIN(u1),请使用括号。否则,先放置内部联接,然后再放置左侧联接。这样可以更容易使用,但 可能会弄乱逻辑。

提示4:除非需要,否则请不要使用LEFT。当您不需要它时,它会使阅读器(和优化器)感到困惑。 (同样,性能没有变化。)

提示5:您为什么使用DISTINCT?这需要对所有结果集进行额外的传递。

如果这些工具还不够用,请提供SHOW CREATE TABLE,以便我们对索引进行评论。