我遇到了SQL查询的问题。我正在开发一个php网站,为了避免提出太多疑问,我更愿意做一个大的看起来像:
select m.*, cj.*, cjb.*, me.pseudo as pseudo_acheteur
from mercato m
JOIN cartes_joueur cj
ON m.ID_carte = cj.ID_carte_joueur
JOIN cartes_joueur_base cjb
ON cj.ID_carte_joueur_base = cjb.ID_carte_joueur_base
JOIN membres me
ON me.ID_membre = cj.ID_membre
where not exists (select * from mercato_encheres me where me.ID_mercato = m.ID_mercato)
and cj.ID_membre = 2
and m.status <> 'cancelled'
ORDER BY total_carac desc, cj.level desc, cjb.nom_carte asc
这应归还会员出售的所有卡,而不会下注。在结果中,我需要所有信息来显示它们。
以下是每个表格中的近似行:
mercato:1200
cartes_joueur:800 000
- carte_joueur_base:62
- membres:2000
- mercato_enchere:15 000
我试图通过删除旧数据来减少它们(在开发环境中);但查询仍然需要10~15秒才能执行(这在网站上太长了)
感谢您的帮助。
答案 0 :(得分:0)
我们来看看。
在*
子句中使用SELECT
对查询效果 。为什么?这很浪费。它不必要地增加了服务器必须处理的数据量,并且在JOIN
s的情况下,可以强制处理具有重复值的列。如果您可以这样做,请尝试枚举所需的列。
您的表可能没有有用的索引来加速这一点。我们无法分辨。请注意,MySQL无法在单个查询中利用多个索引,因此要快速查询,通常需要精心选择的复合索引。我建议你尝试在(ID_membre, ID_carte_jouer, ID_carte_joueur_base)
表上定义索引cartes_joueur
。为什么?您的查询在第一列上匹配相等,然后在ON条件下使用第二列和第三列。
我经常发现用最大的表(大多数行)编写查询有助于我清楚地思考优化问题。在您的情况下,您的最大表格为cartes_jouer
,您只从该表中选择一个ID_membre
值。您最明确的优化途径是您只需要检查该表中大约400行而不是800 000行的知识。适当的复合索引将使这成为可能,并且最容易想象索引的列如果表格在您的查询中排在第一位。
你有一个相关的子查询 - 这个。
where not exists (select *
from mercato_encheres me
where me.ID_mercato = m.ID_mercato)
MySQL的查询计划程序在看到它时可能是愚蠢的字面意思,运行数千次。在你的情况下,它更糟糕:它有SELECT *
:见上面的第1点。
应该重构使用LEFT JOIN ... IS NULL
模式。这是怎么回事。
select whatever
from mercato m
JOIN ...
JOIN ...
LEFT JOIN mercato_encheres mench ON mench.ID_mercato = m.ID_mercato
WHERE mench.ID_mercato IS NULL
and ...
ORDER BY ...
说明:LEFT JOIN
而不是普通内部JOIN
的使用允许mercato
表中的行保留在输出中,即使ON条件与它们中的表不匹配也是如此mercato_encheres
表。不匹配的行为第二个表获取NULL值。 mench.ID_mercato IS NULL
子句中的WHERE
条件然后仅选择 不匹配的行。