简体   繁体   English

SQL / PHP查询优化

[英]SQL/PHP query optimization

I'm looking for help with optimizing queries and understanding how to do it myself in the future. 我正在寻找有关优化查询的帮助,并希望以后自己了解如何做。

I've got the DB exported for easy use - https://www.dropbox.com/s/jwocqwuxl1bv3rt/DB_BF.zip?dl=0 我已经导出了数据库以方便使用-https://www.dropbox.com/s/jwocqwuxl1bv3rt/DB_BF.zip?dl=0

The queries loading times can be seen on these pages - 在这些页面上可以看到查询的加载时间-

http://89.163.173.82/DCS/blueflag/Pilots.php http://89.163.173.82/DCS/blueflag/Pilots.php

http://89.163.173.82/DCS/blueflag/Events.php http://89.163.173.82/DCS/blueflag/Events.php

http://89.163.173.82/DCS/blueflag/Player.php?term=Reaper6 http://89.163.173.82/DCS/blueflag/Player.php?term=Reaper6

So far I tried to do some optimizations by adding indexes and reducing the selected columns, but no big effect. 到目前为止,我尝试通过添加索引和减少选定的列来进行一些优化,但是效果不大。 I'm not sure how to alter these big queries to do the same procedure but optimized. 我不确定如何更改这些大查询以执行相同的步骤,但已对其进行了优化。

First query- 第一次查询

SELECT DeadTbl.TIME AS 'Time',DeadTbl.Event AS 'Event',DeadTbl.InitiatorCoa AS 'Target Coalition',DeadTbl.InitiatorPlayer AS 'Target Player',DeadTbl.InitiatorType AS 'Target Type',DeadTbl.InitiatorGroupCat
    ,HitTbl.InitiatorCoa AS 'Coalition',HitTbl.InitiatorPlayer AS 'Player',HitTbl.InitiatorType AS 'Type',HitTbl.WeaponCat AS 'Weapon Category',HitTbl.WeaponName AS 'Weapon Name'
FROM (
    SELECT TIME,InitiatorID,EVENT,InitiatorCoa,InitiatorType,InitiatorPlayer,InitiatorGroupCat
    FROM BlueFlagR2
    WHERE (EVENT = 'S_EVENT_DEAD'OR EVENT = 'S_EVENT_CRASH'OR EVENT = 'S_EVENT_PLAYER_LEAVE_UNIT')
        AND InitiatorGroupCat != ''
    ) AS DeadTbl
JOIN (
    SELECT MAX(`Time`) AS `Time`
        ,InitiatorID,InitiatorCoa,InitiatorPlayer,InitiatorType
        ,WeaponCat,WeaponName
        ,TargetID,TargetCoa,TargetType,TargetPlayer
    FROM BlueFlagR2
    WHERE EVENT = 'S_EVENT_HIT'
        AND InitiatorID != 0
        AND InitiatorPlayer != 'No Initiator'
    GROUP BY InitiatorID,InitiatorPlayer,TargetID,TargetType
) AS HitTbl ON DeadTbl.InitiatorID = HitTbl.TargetID
    AND DeadTbl.InitiatorCoa = HitTbl.TargetCoa
    AND DeadTbl.InitiatorPlayer = HitTbl.TargetPlayer
    AND DeadTbl.InitiatorType = HitTbl.TargetType
    AND HitTbl.TIME <= DeadTbl.TIME
GROUP BY DeadTbl.InitiatorID,DeadTbl.TIME,HitTbl.InitiatorID
ORDER BY DeadTbl.TIME ASC

Second query: 第二个查询:

SELECT K.Player AS Player, K.Ground AS Ground, K.Airplane AS Airplane, K.Helicopter AS Helicopter, K.Ship AS Ship, K.Total AS Total, IFNULL(D.Total,0) AS Deaths, (CASE WHEN D.Total IS NULL THEN K.Total ELSE K.Total/D.Total END) AS KD_Ratio
FROM 
(
SELECT PlayerTable.Player AS 'Player', SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'GROUND_UNIT' THEN 1 ELSE 0 END) AS Ground, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'AIRPLANE' THEN 1 ELSE 0 END) AS Airplane, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'HELICOPTER' THEN 1 ELSE 0 END) AS Helicopter, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'SHIP' THEN 1 ELSE 0 END) AS Ship, COUNT(PlayerTable.`Target Player`) AS Total
FROM
(
    SELECT DeadTbl.Time AS 'Time', HitTbl.InitiatorCoa AS 'Coalition', HitTbl.InitiatorPlayer AS 'Player', HitTbl.InitiatorType AS 'Type',HitTbl.WeaponCat AS 'Weapon Category',HitTbl.WeaponName AS 'Weapon Name', DeadTbl.Event AS 'Event', DeadTbl.InitiatorCoa AS 'Target Coalition', DeadTbl.InitiatorPlayer AS 'Target Player', DeadTbl.InitiatorType AS 'Target Type', DeadTbl.InitiatorGroupCat
    FROM 
        (
        SELECT TIME,InitiatorID,EVENT,InitiatorCoa,InitiatorType,InitiatorPlayer,InitiatorGroupCat
        FROM BlueFlagR2
        WHERE (EVENT = 'S_EVENT_DEAD' OR EVENT = 'S_EVENT_CRASH' OR EVENT='S_EVENT_PLAYER_LEAVE_UNIT')
        AND InitiatorGroupCat != ''
        ) AS DeadTbl
    JOIN
        (
        SELECT MAX(`Time`) AS `Time`,InitiatorID,InitiatorCoa,InitiatorPlayer,InitiatorType,WeaponCat,WeaponName,TargetID,TargetCoa,TargetType,TargetPlayer
        FROM BlueFlagR2
        WHERE EVENT = 'S_EVENT_HIT' AND InitiatorID!=0 AND InitiatorPlayer!='No Initiator'
        GROUP BY InitiatorID,InitiatorPlayer,TargetID,TargetType
        ) AS HitTbl
    ON DeadTbl.InitiatorID = HitTbl.TargetID AND DeadTbl.InitiatorCoa = HitTbl.TargetCoa AND DeadTbl.InitiatorPlayer = HitTbl.TargetPlayer AND DeadTbl.InitiatorType = HitTbl.TargetType AND HitTbl.Time <= DeadTbl.Time
    GROUP BY DeadTbl.InitiatorID,DeadTbl.Time,HitTbl.InitiatorID
) AS PlayerTable
GROUP BY PlayerTable.Player
) AS K
LEFT JOIN
(
SELECT InitiatorPlayer, COUNT(*) AS Total
FROM BlueFlagR2
WHERE (EVENT = 'S_EVENT_DEAD' OR EVENT = 'S_EVENT_CRASH')
AND (InitiatorGroupCat = 'AIRPLANE' OR InitiatorGroupCat = 'HELICOPTER')
AND InitiatorPlayer != 'AI'
GROUP BY InitiatorPlayer
) AS D
ON K.Player = D.InitiatorPlayer
WHERE Player != 'AI' AND Player != '' AND Player != 'No Initiator'
ORDER BY CASE WHEN KD_Ratio = 'Infinite' THEN K.Total
ELSE KD_Ratio END DESC

They are basically similar as the core of it is the same. 它们基本上是相似的,因为其核心是相同的。

Appreciate any help! 感谢任何帮助!

You're also using an or where you may be able to use in 您还在使用可以在其中使用的位置

WHERE EVENT in ( 'S_EVENT_DEAD', 'S_EVENT_CRASH', 'S_EVENT_PLAYER_LEAVE_UNIT') (“ S_EVENT_DEAD”,“ S_EVENT_CRASH”,“ S_EVENT_PLAYER_LEAVE_UNIT”中的事件

Or is very slow use it sparingly and always list the most likely outcome first in the arguments. 还是非常缓慢地谨慎使用它,并始终在参数中首先列出最可能的结果。

Optimized First query- 优化的第一个查询-

    SELECT  * 
    INTO    #BlueFlagR2IGC
    FROM    BlueFlagR2

    DELETE FROM #BlueFlagR2IGC
    WHERE InitiatorGroupCat != ''


    SELECT  * 
    INTO    #BlueFlagR2IP
    FROM    BlueFlagR2

    DELETE FROM #BlueFlagR2IP
    WHERE InitiatorID = 0
    AND InitiatorPlayer = 'No Initiator'


    SELECT DeadTbl.TIME AS 'Time',DeadTbl.Event AS 'Event',DeadTbl.InitiatorCoa AS 'Target Coalition',DeadTbl.InitiatorPlayer AS 'Target Player',DeadTbl.InitiatorType AS 'Target Type',DeadTbl.InitiatorGroupCat
        ,HitTbl.InitiatorCoa AS 'Coalition',HitTbl.InitiatorPlayer AS 'Player',HitTbl.InitiatorType AS 'Type',HitTbl.WeaponCat AS 'Weapon Category',HitTbl.WeaponName AS 'Weapon Name'
    FROM (
        SELECT TIME,InitiatorID,EVENT,InitiatorCoa,InitiatorType,InitiatorPlayer,InitiatorGroupCat
        FROM #BlueFlagR2IGC
        WHERE EVENT in ('S_EVENT_DEAD','S_EVENT_CRASH','S_EVENT_PLAYER_LEAVE_UNIT')

        ) AS DeadTbl
    JOIN (
        SELECT MAX(`Time`) AS `Time`
            ,InitiatorID,InitiatorCoa,InitiatorPlayer,InitiatorType
            ,WeaponCat,WeaponName
            ,TargetID,TargetCoa,TargetType,TargetPlayer
        FROM #BlueFlagR2IP
        WHERE EVENT = 'S_EVENT_HIT'
        GROUP BY InitiatorID,InitiatorPlayer,TargetID,TargetType
    ) AS HitTbl ON DeadTbl.InitiatorID = HitTbl.TargetID
        AND DeadTbl.InitiatorCoa = HitTbl.TargetCoa
        AND DeadTbl.InitiatorPlayer = HitTbl.TargetPlayer
        AND DeadTbl.InitiatorType = HitTbl.TargetType
        AND HitTbl.TIME <= DeadTbl.TIME
    GROUP BY DeadTbl.InitiatorID,DeadTbl.TIME,HitTbl.InitiatorID
    ORDER BY DeadTbl.TIME ASC


    drop table #BlueFlagR2IGC
   drop table #BlueFlagR2IP

Optimized Second query: 优化第二查询:

SELECT  * 
INTO    #BlueFlagR2IGC
FROM    BlueFlagR2

DELETE FROM #BlueFlagR2IGC
WHERE InitiatorGroupCat != ''


SELECT  * 
INTO    #BlueFlagR2IP
FROM    BlueFlagR2

DELETE FROM #BlueFlagR2IP
WHERE InitiatorID = 0
AND InitiatorPlayer = 'No Initiator'


SELECT  * 
INTO    #BlueFlagR2AI
FROM    BlueFlagR2

DELETE FROM #BlueFlagR2AI
WHERE InitiatorPlayer = 'AI'


if OBJECT_ID('tempdb..#target') is not null 
drop table #target

SELECT K.Player AS Player, K.Ground AS Ground, K.Airplane AS Airplane, K.Helicopter AS Helicopter, K.Ship AS Ship, K.Total AS Total, IFNULL(D.Total,0) AS Deaths, (CASE WHEN D.Total IS NULL THEN K.Total ELSE K.Total/D.Total END) AS KD_Ratio
INTO #target
FROM 
(
SELECT PlayerTable.Player AS 'Player', SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'GROUND_UNIT' THEN 1 ELSE 0 END) AS Ground, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'AIRPLANE' THEN 1 ELSE 0 END) AS Airplane, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'HELICOPTER' THEN 1 ELSE 0 END) AS Helicopter, SUM(CASE WHEN PlayerTable.InitiatorGroupCat = 'SHIP' THEN 1 ELSE 0 END) AS Ship, COUNT(PlayerTable.`Target Player`) AS Total
FROM
(
    SELECT DeadTbl.Time AS 'Time', HitTbl.InitiatorCoa AS 'Coalition', HitTbl.InitiatorPlayer AS 'Player', HitTbl.InitiatorType AS 'Type',HitTbl.WeaponCat AS 'Weapon Category',HitTbl.WeaponName AS 'Weapon Name', DeadTbl.Event AS 'Event', DeadTbl.InitiatorCoa AS 'Target Coalition', DeadTbl.InitiatorPlayer AS 'Target Player', DeadTbl.InitiatorType AS 'Target Type', DeadTbl.InitiatorGroupCat
    FROM 
        (
        SELECT TIME,InitiatorID,EVENT,InitiatorCoa,InitiatorType,InitiatorPlayer,InitiatorGroupCat
        FROM #BlueFlagR2IGC
        WHERE EVENT in ('S_EVENT_DEAD','S_EVENT_CRASH','S_EVENT_PLAYER_LEAVE_UNIT')
        ) AS DeadTbl
    JOIN
        (
        SELECT MAX(`Time`) AS `Time`,InitiatorID,InitiatorCoa,InitiatorPlayer,InitiatorType,WeaponCat,WeaponName,TargetID,TargetCoa,TargetType,TargetPlayer
        FROM #BlueFlagR2IP
        WHERE EVENT = 'S_EVENT_HIT' 
        GROUP BY InitiatorID,InitiatorPlayer,TargetID,TargetType
        ) AS HitTbl
    ON DeadTbl.InitiatorID = HitTbl.TargetID AND DeadTbl.InitiatorCoa = HitTbl.TargetCoa AND DeadTbl.InitiatorPlayer = HitTbl.TargetPlayer AND DeadTbl.InitiatorType = HitTbl.TargetType AND HitTbl.Time <= DeadTbl.Time
    GROUP BY DeadTbl.InitiatorID,DeadTbl.Time,HitTbl.InitiatorID
) AS PlayerTable
GROUP BY PlayerTable.Player
) AS K



DELETE FROM #target
WHERE Player = 'AI' 
AND Player = '' 
AND Player = 'No Initiator'

SELECT  k.*
FROM    #target k
LEFT JOIN
(
SELECT InitiatorPlayer, COUNT(*) AS Total
FROM #BlueFlagR2AI
WHERE EVENT in ('S_EVENT_DEAD', 'S_EVENT_CRASH')
AND     InitiatorGroupCat in ( 'AIRPLANE', 'HELICOPTER')
GROUP BY InitiatorPlayer
) AS D
ON K.Player = D.InitiatorPlayer
ORDER BY CASE WHEN KD_Ratio = 'Infinite' THEN K.Total
ELSE KD_Ratio END DESC

drop table #BlueFlagR2IGC
drop table #BlueFlagR2IP
drop table #BlueFlagR2AI

i have updated for drop table for MY SQL. 我已经为我的SQL更新了删除表。 i am not sure how to do that in MY SQL. 我不确定如何在MY SQL中执行此操作。 Just sure about that if we use not equal (!=) in query will take more time. 只要确定,如果我们在查询中使用不等于(!=),将花费更多时间。

I think the real issue isn't in the sql itself, but in the way you created the database. 我认为真正的问题不在于sql本身,而在于创建数据库的方式。 you are using varchars to almost everything. 您正在使用varchars几乎所有内容。 That is not a good database-structure. 那不是一个好的数据库结构。 You should create new tables for weapons, weaponscategory etc... and create relationsships to those tables. 您应该为武器,武器类别等创建新表,并创建与这些表的关系。 That's the whole point of using a relational database! 这就是使用关系数据库的全部要点! :-) :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM