簡體   English   中英

改善SQL查詢

[英]Improve a SQL query

由於SQL查詢,我檢索了一個需要很長時間才能運行的項目。

我想知道您是否知道一種改進方法。 至少有辦法改善它。

據我所知,查詢返回了1500行,並從其他表中求和。

SELECT
p.id,
p.datecreate,
p.title,
p.address,
p.address2,
p.code_postal,
p.ville,
p.description,
p.description_admin,
p.idstatut,
p.idstatut_admin,
p.reference,
p.star,
p.logo,
p.deleted,
cc.value as starcolor,
p.idsociete,
soc.nom as societe_nom,
s.titlestatut,
s.fontcolor,
s.label as label,
sa.titlestatut as titlestatut_admin,
sa.fontcolor as fontcolor_admin,
sa.label as label_admin,
(SELECT SUM(nbr) FROM plans as cplans WHERE cplans.idprojets = p.id) as count_commandes,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '1' AND cfiles.bat_valid = '0') as count_averifier,
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide = '0') as count_modif_nohide,
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide IN (1)) as count_modif_hide,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '0') as count_bat_attente,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '1') as count_bat_valider
FROM projets as p INNER JOIN societe AS soc ON p.idsociete = soc.id
INNER JOIN statuts AS s ON p.idstatut = s.id
INNER JOIN statuts AS sa ON p.idstatut_admin = sa.id
LEFT JOIN const AS cc ON cc.name = p.star AND cc.parent = 'star'
WHERE  p.idstatut IN (3)
AND p.deleted = 0
GROUP BY p.id
ORDER BY p.datecreate DESC

感謝大伙們 !

編輯-----

我在這里做了什么,會更好嗎?

SELECT
    p.id,
    p.datecreate,
    p.title,
    p.address,
    p.address2,
    p.code_postal,
    p.ville,
    p.description,
    p.description_admin,
    p.idstatut,
    p.idstatut_admin,
    p.reference,
    p.star,
    p.logo,
    p.deleted,
    cc.value as starcolor,
    p.idsociete,
    soc.nom as societe_nom,
    s.titlestatut,
    s.fontcolor,
    s.label as label,
    sa.titlestatut as titlestatut_admin,
    sa.fontcolor as fontcolor_admin,
    sa.label as label_admin,
    CC.count_commandes,
    CA.count_averifier,
    CMN.count_modif_nohide,
    CMH.count_modif_hide,
    CBA.count_bat_attente,
    CBV.count_bat_valider
FROM
    projets as p
        INNER JOIN societe AS soc
            ON p.idsociete = soc.id
        INNER JOIN statuts AS s
            ON p.idstatut = s.id
        INNER JOIN statuts AS sa
            ON p.idstatut_admin = sa.id
        LEFT JOIN const AS cc
            ON cc.name = p.star
            AND cc.parent = 'star'
        LEFT JOIN (

                SELECT idprojets, SUM(nbr) as count_commandes
                FROM plans
                GROUP BY idprojets
            ) AS CC
            ON p.id = CC.idprojets
        LEFT JOIN (

                SELECT idprojets, COUNT(*) AS count_averifier
                FROM files
                GROUP BY idprojets
                WHERE cfiles.folder = 1 AND cfiles.bat_valid = 0
            ) AS CA
            ON p.id = CA.idprojets
        LEFT JOIN (

                SELECT idprojets, COUNT(*) as count_modif_nohide
                FROM files_modif_title
                WHERE statut = 7 AND hide = 0
                GROUP BY idprojets
            ) AS CMN
            ON p.id = CMN.idprojets
        LEFT JOIN (

                SELECT idprojets, COUNT(*) as count_modif_hide
                FROM files_modif_title
                WHERE statut = 7 AND hide = 1
                GROUP BY idprojets
            ) AS CMH
            ON p.id = CMH.idprojets
        LEFT JOIN (

                SELECT idprojets, COUNT(*)
                FROM files
                WHERE folder = 2 AND bat_valid = 0
                GROUP BY idprojets
            ) AS CBA
            ON p.id = CBA.idprojets
        LEFT JOIN (

                SELECT idprojets, COUNT(*)
                FROM files
                WHERE folder = 2 AND bat_valid = 1
                GROUP BY idprojets
            ) AS CBV
            ON p.id = CBV.idprojets
WHERE
    p.idstatut IN (3)
    AND p.deleted = 0
GROUP BY p.id
ORDER BY p.datecreate DESC;

感謝您的發言,主要問題是6個SELECT嵌入在SELECT子句中。 對於應用程序放在一起的每個記錄,都會對它們進行評估,因此它會執行1500 x 6 = 9000個查詢! 通過這樣做,我有了9001個查詢,現在只有7個查詢,因為子查詢在運行時僅被評估一次。 那是對的嗎 ?

這是您要改進的部分:

(SELECT SUM(nbr) FROM plans as cplans WHERE cplans.idprojets = p.id) as count_commandes,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '1' AND cfiles.bat_valid = '0') as count_averifier,
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide = '0') as count_modif_nohide,
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide IN (1)) as count_modif_hide,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '0') as count_bat_attente,
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '1') as count_bat_valider

您可以為此使用條件聚合,並且只能將表連接一次:

count(nbr) as..,
count(CASE WHEN cfiles.folder = '1' and cfiles.bat_valid = '0' then id END) as ..,
count(CASE WHEN cfiles.folder = '2' and cfiles.bat_valid = '0' then id END) as ..,
count(CASE WHEN cfiles.folder = '2' and cfiles.bat_valid = '1' then id END) as ..,
........

添加聯接

JOIN files cfiles
 ON(cfiles.idprojets = p.id)

files_modif_title做完全相同的files_modif_title

  1. 希望您的主表具有索引
  2. 代替使用子查詢,使用join

嘗試,

SELECT
p.id,
p.datecreate,
p.title,
p.address,
p.address2,
p.code_postal,
p.ville,
p.description,
p.description_admin,
p.idstatut,
p.idstatut_admin,
p.reference,
p.star,
p.logo,
p.deleted,
cc.value as starcolor,
p.idsociete,
soc.nom as societe_nom,
s.titlestatut,
s.fontcolor,
s.label as label,
sa.titlestatut as titlestatut_admin,
sa.fontcolor as fontcolor_admin,
sa.label as label_admin,
count (case when cfiles.folder = '2' AND cfiles.bat_valid = '0' then 1 end ) count_bat_attente,
count (case when cfiles.folder = '1' AND cfiles.bat_valid = '0' then 1 end ) count_averifier,
count (case when cfiles.folder = '2' AND cfiles.bat_valid = '1' then 1 end) count_bat_valider,
SUM(nbr) as count_commandes,
count (case when cfmt.statut = '7' AND cfmt.hide = '0' then 1 end) count_modif_nohide,
count (case when cfmt.statut = '7' AND cfmt.hide IN (1) then 1 end) count_modif_hide

FROM projets as p INNER JOIN societe AS soc ON p.idsociete = soc.id
INNER JOIN statuts AS s ON p.idstatut = s.id
INNER JOIN statuts AS sa ON p.idstatut_admin = sa.id
left join files on files.idprojets=p.id
left join plans cplans on cplans.idprojets = p.id
left join files_modif_title cfmt on cfmt.idprojets = p.id
LEFT JOIN const AS cc ON cc.name = p.star AND cc.parent = 'star'
WHERE  p.idstatut IN (3)
AND p.deleted = 0
GROUP BY p.id
ORDER BY p.datecreate DESC

要回答您的問題“這是我做的,會更好嗎?”,...

盡管您的9001邏輯有效,但是還有另一個問題... LEFT JOIN ( SELECT ... )正在建立一個具有一定行數(1500?)的臨時表。 如果您運行的是5.6之前的版本,則這些tmp表沒有索引,必須重復掃描。 現在,我們談論的是1500 * 1500 * 6 =數百萬次操作,而不僅僅是9001。

即使使用5.6,也需要額外的步驟(6次)來發現最佳索引並進行構建。

但是,您真正的問題是“我怎樣才能加快速度?”。 其他人在回答這個問題上做得很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM