我检索了一个由于SQL查询而需要很长时间才能运行的项目。
我想知道你是否知道如何改进它。 至少如果有办法改进它。
据我所知,查询返回1500行,并从其他表中生成SUM和COUNT。
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;
感谢您所说的,主要问题是SELECT子句中嵌入了6个SELECT。这些是针对应用程序放在一起的每条记录进行评估,因此它执行1500 x 6 = 9000个查询! 通过这样做,我有9001个查询,现在只有7个,因为子查询在运行时只被评估一次。这是对的吗?
答案 0 :(得分:2)
这是你想要改进的部分:
(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
答案 1 :(得分:1)
答案 2 :(得分:1)
试,
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
答案 3 :(得分:1)
回答你的问题“我在这里做了什么,可能会更好吗?”,......
尽管您的9001逻辑有效,但还有另一个问题...... LEFT JOIN ( SELECT ... )
正在构建一些行数(1500?)的临时表。如果您在5.6之前运行版本,则这些tmp表没有索引,必须重复扫描。现在我们谈论1500 * 1500 * 6 =数百万次操作,而不仅仅是9001。
即使使用5.6,也有额外的步骤(6次)来发现最佳索引并构建它。
但是,你真正的问题是“我怎样才能加快速度?”。其他人已经很好地回答了这个问题。