简体   繁体   English

使用多个左联接,按组和顺序进行mysql优化

[英]mysql optimization with multiple left joins, group by and order

I'm experiencing some difficulties with my queries which contains multiple left joins in combination with a group by and order. 我的查询遇到一些困难,其中包含多个左联接以及group by和order。

Text table and textdetails contain +- 800k records 文本表和textdetails包含+-80万条记录
Copy table and copydetails contain +- 200k records 复制表和copydetails包含+-200k记录
Other tables are a lot smaller. 其他表要小得多。

I have foreign keys for every column I perform a left join on. 对于执行左连接的每一列,我都有外键。 I also have indexes on every column on which I perform a where statement. 我在执行where语句的每一列上都有索引。 Still the MySQL query below runs approx 40 seconds. 下面的MySQL查询仍然运行约40秒。 Leaving out the Group By improves a bit. 排除Group By会有所改善。 Leaving out the Order By improves a lot. 省略订单依据可以改善很多。

I did some research but I'm still confused on how to improve my query or indexes. 我做了一些研究,但是我仍然对如何改善查询或索引感到困惑。

SELECT * FROM `copy` 
LEFT JOIN `domain` ON domain.domain_id = copy.copy_domain_id 
LEFT JOIN `domaincategory` ON copy.copy_domain_id = domaincategory.domaincategory_domain_id AND domaincategory.domaincategory_account_id = copy.copy_account_id 
LEFT JOIN `text` ON text.text_id = copy.copy_text_id LEFT JOIN `textdetails` ON textdetails.textdetails_text_id = text.text_id 
LEFT JOIN `channel` ON channel.channel_domain_id = domain.domain_id AND channel.channel_account_id = copy.copy_account_id 
LEFT JOIN `feed` ON feed.feed_id = text.text_feed_id 
WHERE (feed.feed_account_id = 96) AND (feed.feed_flag_delete IS NULL) AND (text.text_flag_delete IS NULL) AND (copy.copy_flag_delete IS NULL) AND (copy.copy_tracking_date_found IS NOT NULL) AND (channel.channel_active = 1) 
GROUP BY `copy`.`copy_id`
ORDER BY `copy`.`copy_tracking_date_found` DESC LIMIT 50 

The result of the EXPLAIN option is shown below but I can't figure out how to read it and use it properly EXPLAIN选项的结果如下所示,但我不知道如何阅读和正确使用它

ID  : 1
Select_type : SIMPLE
Table : Feed
Type : Ref
Possible_Keys: PRIMARY,fk_feed_account_id,feed_flag_delete
Key: fk_feed_account_id
Key_len : 4:
Ref : const
Rows : 1
Extra: Using where; Using temporary; Using filesort


ID  : 1
Select_type : SIMPLE
Table : text
Type : Ref
Possible_Keys: PRIMARY,fk_text_feed_id,text_flag_delete
Key: text_flag_delete
Key_len : 2
Ref : const
Rows : 2628
Extra: Using where


ID  : 1
Select_type : SIMPLE
Table : textdetails
Type : Ref
Possible_Keys: fk_textdetails_text_id
Key: fk_textdetails_text_id
Key_len : 5
Ref : text.text_id
Rows : 1
Extra:


ID  : 1
Select_type : SIMPLE
Table : copy
Type : Ref
Possible_Keys: fk_copy_account_id,fk_copy_domain_id,fk_copy_text_...
Key: fk_copy_text_id
Key_len : 4
Ref : text.text_id
Rows : 1
Extra: Using where


ID  : 1
Select_type : SIMPLE
Table : domain
Type : eq_ref
Possible_Keys: PRIMARY
Key: PRIMARY
Key_len : 4
Ref : copy.copy_domain_id
Rows : 1
Extra: Using where


ID  : 1
Select_type : SIMPLE
Table : domaincategory
Type : eq_ref
Possible_Keys: fk_domaincategory_account_id,fk_domaincategory_dom
Key: fk_domaincategory_domain_id
Key_len : 4
Ref : domain.domain_id
Rows : 1
Extra:


ID  : 1
Select_type : SIMPLE
Table : channel
Type : ref
Possible_Keys: fk_channel_account_id,fk_channel_domain_id,channel...
Key: fk_channel_domain_id
Key_len : 4
Ref : copy.copy_domain_id
Rows : 2
Extra: Using where

Perhaps I should explain the relations a little bit more? 也许我应该多说明一些关系?
feed : text = 1:n feed:文字= 1:n
text : textdetails = 1:1 文字:textdetails = 1:1
text : copy = 1:n 文字:复制= 1:n
copy : domain = n:1 复制:域= n:1
channel : domain n:1 频道:网域n:1

Quite a few things I would change and have updated the query to reflect that. 我将做很多更改,并更新了查询以反映这一点。 Also, for indexes. 另外,用于索引。 If you have indexes on every column, but they are individual indexes, that WONT necessarily help you. 如果您在每列上都有索引,但是它们是单独的索引,那么WONT一定会为您提供帮助。 You need compound (multiple field) indexes to better match your join / where criteria and groupings if possible. 您需要复合(多字段)索引以更好地匹配您的联接/(如果可能)条件和分组。

SELECT 
      * 
   FROM 
      feed f 
         JOIN text t
            ON feed.feed_id = t.text_feed_id
            LEFT JOIN textdetails td 
               ON t.text_id = td.textdetails_text_id 
            JOIN COPY c
               ON t.text_id = c.copy_text_id 
               LEFT JOIN domain d
                  ON c.copy_domain_id = d.domain_id
               LEFT JOIN domaincategory dc 
                  ON  c.copy_domain_id = dc.domaincategory_domain_id 
                  AND c.copy_account_id = cd.domaincategory_account_id
               JOIN channel ch 
                  ON  c.copy_account_id = ch.channel_account_id 
                  AND c.copy_domain_id = ch.channel_domain_id
                  AND ch.channel_active = 1
   WHERE 
          f.feed_account_id = 96
      AND f.feed_flag_delete IS NULL
      AND t.text_flag_delete IS NULL
      AND c.copy_flag_delete IS NULL
      AND c.copy_tracking_date_found IS NOT NULL
   GROUP BY 
      c.copy_id
   ORDER BY 
      c.copy_tracking_date_found DESC 
   LIMIT 
      50 

Transitive Property 传递性
Since copy.copy_domain_id is a join to domain.domain_id and channel.channel_domain_id is joined to domain.domain_id, we can just change to copy.copy_domain_id = channel.channel_domain_id and not require a split join to different tables on the otherwise same value. 由于copy.copy_domain_id是domain.domain_id的联接,而channel.channel_domain_id是domain.domain_id的联接,因此我们可以更改为copy.copy_domain_id = channel.channel_domain_id,并且不需要以其他方式拆分联接到其他表上。

Second... you have LEFT JOINS, but when you add "feed_account_id = 96", you are automatically converting that into an INNER JOIN as it is a requirement, thus making the TEXT alias a join as well. 其次...您有LEFT JOINS,但是当您添加“ feed_account_id = 96”时,您会根据需要自动将其转换为INNER JOIN,因此也使TEXT别名成为联接。 Similarly with the CHANNEL table having Channel_Active = 1. (I have update query to reflect that). 与Channel_Active = 1的CHANNEL表类似。(我有更新查询来反映这一点)。

Now, since qualifying based on the FEED table for a specific account, I have moved that into the first FROM position and joining down to the Copy table. 现在,由于根据特定帐户的FEED表进行资格认证,因此我将其移至第一个FROM位置并加入了Copy表。

Now, indexes to help optimize this 现在,索引来帮助优化

table        index
feed         ( feed_account_id, feed_id, feed_flag_delete )
text         ( text_feed_id, text_id, text_flag_delete )
textdetails  ( textdetails_text_id )
copy         ( copy_text_id, copy_domain_id, copy_account_id, copy_flag_delete, copy_tracking_date_found, copy_id )
domain       ( domain_id )
domaincategory ( domaincategory_domain_id, domaincategory_account_id )
channel       ( channel_domain_id, channel_account_id, channel_active )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM