解释 SQL 和查询优化

发布于 2024-11-10 16:50:29 字数 1839 浏览 4 评论 0原文

Explain SQL

解释一个耗时超过 5 秒的查询的 SQL(在 phpmyadmin 中)给了我上述内容。我读到我们可以研究解释 SQL 来优化查询。谁能告诉我这个Explain 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的结构表结构。顶部:a 和底部:d

编辑 3:

我想要在此查询中得到什么?

我首先想从表 0_activite 中获取“depart”和“user”(这是一个 id)的值。接下来,我想从 0_member 获取人名(civ、prenom 和 name),我通过“user”从 0_activite 获取其 id,通过匹配 0_activite.user 和 0_member.id。这里department缺少department,它也是一个id。

所以此时,我从两个表 0_activite0_member 中获取了一个人的 Depart、id、civ、nom 和 prenom。

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

然后是更棘手的部分。 0_member 中的一个人可以与多个出发相关联,这存储在 0_depart 中。此外,每个用户都有一个级别,其中之一是“mod”,代表主持人。现在我想获取与第一个用户所在位置不同的所有版主,然后再次从 0_member 中获取这些版主的姓名。我还有一个变量 user_sec,但这在这种情况下可能不太重要,尽管我不能忽视它。

这就是查询变得棘手的原因。 0_member 存储 id、用户名、+ 1 个出发,0_depart 存储用户的所有出发,每个出发一行,0_activite 存储一些其他内容,我想通过 userid 关联这些内容0_activite 以及其余的。

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

再次非常感谢。

Explain SQL

Explain SQL (in phpmyadmin) of a query that is taking more than 5 seconds is giving me the above. I read that we can study the Explain SQL to optimize a query. Can anyone tell if this Explain SQL telling anything as such?

Thanks guys.

Edit:

The query itself:

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

Edit 2:

Structures of the two tables a and dTable structures. Top: a and bottom: d

Edit 3:

What I want in this query?

I first want to get the value of 'depart' and 'user' (which is an id) from the table 0_activite. Next, I want to get name of the person (civ, prenom and name) from 0_member whose id I am getting from 0_activite via 'user', by matching 0_activite.user with 0_member.id. Here depart is short of department which is also an id.

So at this point, I have depart, id, civ, nom and prenom of a person from two tables, 0_activite and 0_member.

Next, I want to know which dr is related with this depart, and this I get from zone_base. The value of depart is same in both 0_activite and 0_member.

Then comes the trickier part. A person from 0_member can be associated with multiple departs and this is stored in 0_depart. Also, every user has a level, one of what is 'mod', stands for moderator. Now I want to get all the people who are moderators in the depart from where the first user is, and then get those moderaor's name from 0_member again. I also have a variable user_sec, but this is probably less important in this context, though I cannot overlook it.

This is what makes the query a tricky one. 0_member is storing id, name of users, + one depart, 0_depart is storing all departs of users, one line for each depart, and 0_activite is storing some other stuffs and I want to relate those through userid of 0_activite and the rest.

Hope I have been clear. If I am not, please let me know and I will try again to edit this post.

Many many thanks again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

左岸枫 2024-11-17 16:50:29

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

您的查询正在 Department 表中按rank = 'mod' 和 user_sec = 2 执行 LEFT 连接。您的总体意图是显示 0_activite 表中的所有记录,而不管 0_Depart 表的有效连接...并且如果存在与 0_Depart 表匹配,您只关心“mod”和 2 值?

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

通过关系或条件在表上拥有键始终会带来性能优势(与没有索引相比)。

首先使用最小的集合开始查询,然后连接到其他表。

从你的问题的澄清开始...我将从最内部开始...它是谁以及他们与哪些部门相关...然后获取版主(来自条件所在的部门)...然后获取实际版主的姓名信息...最后到您的 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

注意我如何对查询进行分层以获取每个部分并连接到下一个、下一个和下一个。我正在根据先前的结果构建链,并使用清晰的“别名”参考来澄清内容。现在,您可以通过其不同的“别名”引用从任何级别获取任何相应元素......

Aside from the few answers provided by the others here, it might help to better understand the "what do I want" from the query. As you've accepted a rather recent answer from me in another of your questions, you have filters applied by department information.

Your query is doing a LEFT join at the Department table by rank = 'mod' and user_sec = 2. Is your overall intent to show ALL records in the 0_activite table REGARDLESS of a valid join to the 0_Depart table... and if there IS a match to the 0_Depart table, you only care about the 'mod' and 2 values?

If you only care about those people specifically associated with the 0_depart with 'mod' and 2 conditions, I would reverse the query starting with THIS table first, then join to the rest.

Having keys on tables via relationship or criteria is always a performance benefit (vs not having the indexes).

Start your query with whatever would be your smallest set FIRST, then join to other tables.

From clarification in your question... I would start with the inner-most... Who it is and what departments are they associated with... THEN get the moderators (from department where condition)... Then get actual moderator's name info... and finally out to your zone_base for the dr based on the department of the MODERATOR...

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

Notice how I tier'd the query to get each part and joined to the next and next and next. I'm building the chain based on the results of the previous with clear "alias" references for clarification of content. Now, you can get whatever respective elements from any of the levels via their distinct "alias" references...

踏雪无痕 2024-11-17 16:50:29

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

从查询来看,0_activite上有user的索引,0_depart上有(depart,rank,user_sec)的索引code> 会在某种程度上提高性能。

The output from EXPLAIN is showing us that the first and third tables listed (a & d) are not having any indexes utilised by the database engine in executing this query. The key column is NULL for both - which is a shame since both are 'large' tables (OK, they're not really large, but compared to the rest of the tables they're the big 'uns).

Judging from the query, an index on user on 0_activite and an index on (depart, rank, user_sec) on 0_depart would go some way to improving performance.

桃酥萝莉 2024-11-17 16:50:29

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

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

处理0_activite
我不确定,但 GROUP 列也应该被索引,因此您需要 a.user 上的密钥

you can see that columns key and key_len are null this means its not using any key in the possible_keys column. So table a and d are both scanning all rows. (check larger numbers in rows column. you want this smaller).

To deal with 0_depart:
Make sure you have a key on (d.depart, d.rank,d.user_sec) which are part of the join of 0_depart.

To deal with 0_activite:
I'm not positive but a GROUP column should be indexed too so you need a key on a.user

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文