解释SQL和查询优化

时间:2011-05-30 22:15:13

标签: mysql phpmyadmin query-optimization

Explain SQL

解释一个超过5秒的查询的SQL(在phpmyadmin中)给出了上述内容。我读到我们可以研究Explain SQL来优化查询。任何人都可以告诉这个解释SQL是否有这样的说法吗?

谢谢你们。

修改

查询本身:

SELECT 
a.`depart` , a.user, 
m.civ, m.prenom, m.nom, 
CAST( GROUP_CONCAT( DISTINCT concat( c.id, '~', c.prenom, ' ', c.nom ) ) AS char ) AS coordinateur, 
z.dr
FROM `0_activite` AS a
JOIN `0_member` AS m ON a.user = m.id
LEFT JOIN `0_depart` AS d ON ( m.depart = d.depart AND d.rank = 'mod' AND d.user_sec =2 )
LEFT JOIN `0_member` AS c ON d.user_id = c.id
LEFT JOIN `zone_base` AS z ON m.depart = z.deprt_num
GROUP BY a.user

编辑2:

两个表ad Table structures的结构。顶部:a和底部:d

编辑3:

在此查询中我想要什么?

我首先要从表0_activite中获取'depart'和'user'(这是一个id)的值。接下来,我希望通过匹配0_member。来自0_activite来获取0_activite来自0_member通过'用户'获取其ID的人(civ,prenom和名称)的名称{1}}。ID。这里的离开是缺少部门,也是一个id。

所以在这一点上,我有一个人的离开,id,civ,nom和prenom来自两个表0_activite0_member

接下来,我想知道哪个博士与此离职有关,而这是我从zone_base得到的。 0_activite0_member中的离开值相同。

然后是棘手的部分。来自0_member的人可以与多个出发相关联,并将其存储在0_depart中。此外,每个用户都有一个级别,其中一个是“mod”,代表主持人。现在我想让第一个用户所在的所有主持人离开,然后再从0_member获取这些模型的名字。我也有一个变量user_sec,但在这种情况下这可能不太重要,但我不能忽视它。

这使得查询变得棘手。 0_member存储id,用户名,+一个离开,0_depart存储用户的所有离开,每个离开一行,0_activite存储其他一些东西,我想通过{{1的用户标识来关联它们其余的。

希望我已经清楚了。如果我不是,请告诉我,我会再次尝试编辑这篇文章。

许多人再次感谢。

3 个答案:

答案 0 :(得分:2)

EXPLAIN的输出向我们显示列出的第一个和第三个表(a& d)在执行此查询时没有使用数据库引擎使用的任何索引。两列的关键列都是NULL - 这是一个耻辱,因为两个都是'大'表(好吧,它们不是很大,但与其他表相比,它们是大'uns)。

根据查询,user上的0_activite索引和(depart, rank, user_sec)上的0_depart上的索引会在某种程度上改善效果。

答案 1 :(得分:2)

您可以看到列keykey_len为空,这意味着它不使用possible_keys列中的任何键。因此,表格ad都会扫描所有行。 (检查行列中的较大数字。您希望它更小)。

处理0_depart: 确保你有一个键(d.depart, d.rank,d.user_sec),它是0_depart连接的一部分。

处理0_activite: 我不是肯定的,但GROUP列也应编入索引,因此您需要a.user上的密钥

答案 2 :(得分:2)

除了这里其他人提供的几个答案之外,从查询中更好地理解“我想要什么”可能会有所帮助。由于您在另一个问题中接受了我最近的回答,因此您可以按部门信息应用过滤器。

您的查询是通过rank ='mod'和user_sec = 2在Department表中进行LEFT连接。您的总体意图是在0_activite表中显示所有记录,并且无法在0_Depart表中显示有效连接...并且如果与0_Depart表匹配,你只关心'mod'和2个值?

如果你只关心与'mod'和2条件的0_depart特别相关的那些人,我会先从THIS表开始反转查询,然后加入其余的。

通过关系或标准在表上创建密钥始终是性能优势(与没有索引相比)。

使用您的最小集合FIRST开始查询,然后加入其他表格。

从你的问题中澄清......我会从最内心开始......它是谁以及它们与哪些部门相关...然后得到主持人(来自部门的条件)......然后得到实际主持人的姓名信息......最后根据MODERATOR的部门发给你的zone_base ...

select STRAIGHT_JOIN
      DeptPerMember.*
      Moderator.Civ as ModCiv,
      Moderator.Prenom as ModPrenom,
      Moderator.Nom as ModNom,
      z.dr
   from 
      ( select
              m.ID,
              m.Depart,
              m.Civ,
              m.Prenom,
              m.Nom
           from
              0_Activite as a
                 join 0_member m
                    on a.User = m.ID
                    join 0_Depart as d
                       on m.depart = d.depart  ) DeptPerMember

      join 0_Depart as DeptForMod
         on DeptPerMember.Depart = DeptForMod.Depart
         and DeptForMod.rank = 'mod'
         and DeptForMod.user_sec = 2 

         join 0_Member as Moderator
            on DeptForMod.user_id = Moderator.ID

            join zone_base z
               on Moderator.depart = z.deprt_num

注意我是如何对查询进行分层以获取每个部分并加入下一个以及下一个和下一个。我正在根据前面的结果构建链,并使用明确的“别名”引用来澄清内容。现在,您可以通过其独特的“别名”引用从任何级别获取任何相应的元素......