【问题标题】:Performance Issues with Derived Table in SQLSQL 中派生表的性能问题
【发布时间】:2011-01-26 17:02:53
【问题描述】:

我在 MySQL 中使用派生表时遇到问题。使用派生表是否会固有地减慢查询的处理速度?

这是我要运行的查询。它不会执行,只是超时。

确实成功了。真的,我已将问题隔离到最后一次加入。当我取出最后一个加入时,它工作正常。但是当我添加最后一个连接时,它拒绝执行。

SELECT cr.COMMUNICATIONS_ID AS ANSWER_ID, 
       cr.CONSUMER_ID as VIEWER_ID, 
       cr.ACTION_LOG_ID, 
       nc.PARENT_COMMUNICATIONS_ID AS QUESTION_ID, 
       nc.SENDER_CONSUMER_ID AS REPLIER_ID, 
       ces.EXPERT_SCORE AS REPLIER_EXPERTISE, 
       cim.CONSUMER_INTEREST_EXPERT_ID AS DOMAIN
    FROM (SELECT 234 AS CONSUMER_ID, 
    ACTION_LOG_ID, 
    COMMUNICATIONS_ID 
    FROM consumer_action_log 
    WHERE COMM_TYPE_ID=4) AS cr
JOIN network_communications AS nc ON 
cr.COMMUNICATIONS_ID=nc.COMMUNICATIONS_ID
JOIN communication_interest_mapping AS cim ON 
nc.PARENT_COMMUNICATIONS_ID=cim.COMMUNICATION_ID
JOIN consumer_expert_score AS ces ON 
nc.SENDER_CONSUMER_ID=ces.CONSUMER_ID
        AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID;

【问题讨论】:

  • 当您单独运行该子查询时会发生什么?它成功了吗?我会单独对子查询进行解释,然后再对整个查询进行解释。
  • 确实成功了。真的,我已将问题隔离到最后一次加入。当我取出最后一个加入时,它工作正常。但是当我添加最后一个连接时,它拒绝执行。
  • 对该查询的 EXPLAIN 的结果是什么?您在每个表中的 consumer_id/expert_id 上都有索引吗?我会推荐一个涵盖每个表中两列的索引。
  • 另外,为了优化帮助,您应该发布每个涉及的表的 SHOW CREATE TABLE 查询的结果(除了 EXPLAIN 的结果)。
  • 我是 SQL 和编程新手。你如何利用索引。还是它们被自动利用了。

标签: sql mysql derived-table


【解决方案1】:

希望这会有所帮助...这里有一些 mysql CREATE INDEX 语句。基本上,如果您可以添加索引,请确保有一个索引覆盖连接 2 个或更多表的每个列。

CREATE INDEX idx_nc
ON network_communications(COMMUNICATIONS_ID);

CREATE INDEX idx_cim
ON communication_interest_mapping(COMMUNICATION_ID);

CREATE INDEX idx_ces
ON consumer_expert_score(CONSUMER_ID, CONSUMER_EXPERT_ID);

派生表本身并不坏,但在这种情况下(见下文),您将从 consumer_action_log 中提取所有 comm_type_id 为 4 的记录。似乎没有与其他表的连接。这可能是sql永远不会返回的原因。

SELECT cr.COMMUNICATIONS_ID, 
           cr.CONSUMER_ID, 
           cr.ACTION_LOG_ID, 
           nc.PARENT_COMMUNICATIONS_ID, 
           nc.SENDER_CONSUMER_ID, 
           ces.EXPERT_SCORE, 
           cim.CONSUMER_INTEREST_EXPERT_ID

    FROM (SELECT 234 AS CONSUMER_ID, 
             ACTION_LOG_ID, 
             COMMUNICATIONS_ID 
             FROM consumer_action_log 
             WHERE COMM_TYPE_ID=4) AS cr

JOIN network_communications AS nc ON 
         cr.COMMUNICATIONS_ID=nc.COMMUNICATIONS_ID

JOIN communication_interest_mapping AS cim ON 
         nc.PARENT_COMMUNICATIONS_ID=cim.COMMUNICATION_ID

JOIN consumer_expert_score AS ces ON 
         nc.SENDER_CONSUMER_ID=ces.CONSUMER_ID
        AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID;

【讨论】:

    【解决方案2】:

    除了 John 在分析器中指出的查找表中应该存在的索引之外,我会确保您的 consumer_action_log 表中的 COMM_TYPE_ID 也有索引。

    然后,在您的子句中添加一个关键字...当查询组织良好而不是依赖查询引擎进行优化时,我总是看到很好的结果...see another sample here

    SELECT STRAIGHT_JOIN
             cr.COMMUNICATIONS_ID AS ANSWER_ID,
             cr.CONSUMER_ID as VIEWER_ID,  
             etc... rest of your query...
    

    可能是优化器正在尝试查看其他表以找出要获取的内容。请参阅我提供的其他 StackOverflow 答案中的 cmets 链接。

    【讨论】:

      猜你喜欢
      • 2012-02-24
      • 1970-01-01
      • 2017-04-30
      • 2017-09-09
      • 2010-09-23
      • 2012-04-23
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多