【问题标题】:Slow running order by for a query that has lots of joins对于具有大量连接的查询,运行排序缓慢
【发布时间】:2013-07-04 12:53:12
【问题描述】:

我问了wrong question,所以我会再试一次(抱歉)。您不必详细阅读查询,而只是为了给您一个想法。

无论如何:有问题的查询是这个,由 Doctrine2 生成的(我删掉了SELECT 部分)

FROM
    tbl_story t0_ 
      LEFT JOIN tbl_user t1_ ON t0_.creator_id = t1_.id 
      LEFT JOIN tbl_image t2_  ON t1_.avatar_id = t2_.id 
      LEFT JOIN tbl_image t3_  ON t0_.id = t3_.story_id 
      LEFT JOIN tbl_like t4_ ON t0_.id = t4_.story_id AND (t4_.creator_id = 3) 
      LEFT JOIN tbl_comment t5_ ON t0_.id = t5_.story_id 
      LEFT JOIN tbl_like t6_  ON t5_.id = t6_.comment_id AND (t6_.creator_id = 3) 
      LEFT JOIN tbl_user t7_  ON t5_.creator_id = t7_.id 
      LEFT JOIN tbl_image t8_ ON t7_.avatar_id = t8_.id 
      LEFT JOIN tbl_location_city t9_  ON t0_.city_id = t9_.id 
      LEFT JOIN tbl_location_state t10_ ON t9_.state_id = t10_.id 
      LEFT JOIN tbl_location_country t11_ ON t10_.country_id = t11_.id 
      LEFT JOIN tbl_story t12_ ON t0_.parent_id = t12_.id 
      LEFT JOIN tbl_page t13_ ON t0_.page_id = t13_.id 
      LEFT JOIN tbl_page_type t14_ ON t13_.page_type_id = t14_.id 
      LEFT JOIN tbl_story_tag t25_  ON t0_.id = t25_.story_id 
      LEFT JOIN tbl_tag t15_ ON t15_.id = t25_.tag_id 
      LEFT JOIN tbl_story_linked_user_reference t16_ ON t0_.id = t16_.story_id 
      LEFT JOIN tbl_user t17_ ON t16_.user_id = t17_.id 
      LEFT JOIN tbl_image t18_ ON t17_.avatar_id = t18_.id 
      LEFT JOIN tbl_story t19_  ON t0_.id = t19_.parent_id 
      LEFT JOIN tbl_album t20_ ON t0_.parent_album_id = t20_.id 
      LEFT JOIN tbl_image t21_ ON t20_.id = t21_.album_id 
      LEFT JOIN tbl_image_linked_user t22_ ON t21_.id = t22_.image_id 
      LEFT JOIN tbl_user t23_ ON t22_.user_id = t23_.id 
      LEFT JOIN tbl_image t24_ ON t23_.avatar_id = t24_.id 
WHERE (
    t0_.creator_id = 3 
    OR t0_.id IN 
        (SELECT 
          t26_.id 
        FROM tbl_story t26_ 
          INNER JOIN tbl_story_circle_visibility t28_ ON t26_.id = t28_.story_id 
          INNER JOIN tbl_circle t27_ ON t27_.id = t28_.circle_id 
          INNER JOIN tbl_user_circle_reference t29_ ON t27_.id = t29_.circle_id 
            AND (t29_.user_id = 3))
    OR t0_.is_public = 1
  ) 
  AND t0_.is_draft = 0 
  AND t0_.type IN (0, 3, 2, 21) 
ORDER BY t0_.created_at DESC
LIMIT 7 

问题: 使用ORDER BY,当 tbl_story(主查询)中只有 31.000 行时,执行查询需要 1.2 秒。如果我删除ORDER BY,它会在 6 毫秒内执行,我想所有这些连接都需要额外的时间,但仍然不用担心。

我首先thought ORDER BY 很慢但我错了。我试过了

SELECT * FROM `tbl_story` ORDER BY created_at DESC LIMIT 7

(同样的东西,但没有连接),它在 2ms 内执行。

我还阅读了其他问题,包括建议删除 JOIN 部分的 this one。如果我在 Doctrine2 中可以这样做,那可能会起作用:

$queryBuilder->select("o.id")->removeLeftJoins()

在我获取 ID 后,在原始查询的克隆中使用它们。

如何解决分页问题?

注意:

即使我完全删除了WHERE 子句,查询也需要同样的 1.2 秒,所以它不会出现问题。

谢谢。

【问题讨论】:

  • 我从早上开始就很难过,但你让我的一天 ROFL :D
  • 你能发布并解释查询吗?我怀疑您加入的某些表没有使用索引列
  • pastebin.com/6evBkJF3 有点难以阅读,因为它有 30 行。当 Doctrine2 找到任何类型的关系时,它会自动创建索引。
  • @MoeedFarooqui 我的问题没有什么好笑的。如果你知道答案,请赐教:)
  • 它在 tbl_story (t0_) 上没有使用索引,而且似乎也错过了 tbl_image_linked_user (t22_)。对于 tbl_story,在类型 AND is_draft AND created_at 上添加一个索引,尽管这可能没有多大帮助。为了更进一步,您可能需要将其拆分为 3 个联合在一起的查询,以允许它使用有用的索引。

标签: mysql sql doctrine-orm


【解决方案1】:

我怀疑基于 type 和 is_draft 的索引可能不足以缩小范围,让 MySQL 无法注意到这些索引。

如果您在 creator_id 上有一个索引,在 is_public 上有一个索引,在 id 上有另一个(我假设您这样做,因为它可能是主 id),那么像这样的 3 个联合查询可能会有所帮助。

SELECT *
FROM
    tbl_story t0_ 
      LEFT JOIN tbl_user t1_ ON t0_.creator_id = t1_.id 
      LEFT JOIN tbl_image t2_  ON t1_.avatar_id = t2_.id 
      LEFT JOIN tbl_image t3_  ON t0_.id = t3_.story_id 
      LEFT JOIN tbl_like t4_ ON t0_.id = t4_.story_id AND (t4_.creator_id = 3) 
      LEFT JOIN tbl_comment t5_ ON t0_.id = t5_.story_id 
      LEFT JOIN tbl_like t6_  ON t5_.id = t6_.comment_id AND (t6_.creator_id = 3) 
      LEFT JOIN tbl_user t7_  ON t5_.creator_id = t7_.id 
      LEFT JOIN tbl_image t8_ ON t7_.avatar_id = t8_.id 
      LEFT JOIN tbl_location_city t9_  ON t0_.city_id = t9_.id 
      LEFT JOIN tbl_location_state t10_ ON t9_.state_id = t10_.id 
      LEFT JOIN tbl_location_country t11_ ON t10_.country_id = t11_.id 
      LEFT JOIN tbl_story t12_ ON t0_.parent_id = t12_.id 
      LEFT JOIN tbl_page t13_ ON t0_.page_id = t13_.id 
      LEFT JOIN tbl_page_type t14_ ON t13_.page_type_id = t14_.id 
      LEFT JOIN tbl_story_tag t25_  ON t0_.id = t25_.story_id 
      LEFT JOIN tbl_tag t15_ ON t15_.id = t25_.tag_id 
      LEFT JOIN tbl_story_linked_user_reference t16_ ON t0_.id = t16_.story_id 
      LEFT JOIN tbl_user t17_ ON t16_.user_id = t17_.id 
      LEFT JOIN tbl_image t18_ ON t17_.avatar_id = t18_.id 
      LEFT JOIN tbl_story t19_  ON t0_.id = t19_.parent_id 
      LEFT JOIN tbl_album t20_ ON t0_.parent_album_id = t20_.id 
      LEFT JOIN tbl_image t21_ ON t20_.id = t21_.album_id 
      LEFT JOIN tbl_image_linked_user t22_ ON t21_.id = t22_.image_id 
      LEFT JOIN tbl_user t23_ ON t22_.user_id = t23_.id 
      LEFT JOIN tbl_image t24_ ON t23_.avatar_id = t24_.id 
WHERE t0_.creator_id = 3 
  AND t0_.is_draft = 0 
  AND t0_.type IN (0, 3, 2, 21) 
UNION
SELECT *
FROM
    tbl_story t0_ 
      LEFT JOIN tbl_user t1_ ON t0_.creator_id = t1_.id 
      LEFT JOIN tbl_image t2_  ON t1_.avatar_id = t2_.id 
      LEFT JOIN tbl_image t3_  ON t0_.id = t3_.story_id 
      LEFT JOIN tbl_like t4_ ON t0_.id = t4_.story_id AND (t4_.creator_id = 3) 
      LEFT JOIN tbl_comment t5_ ON t0_.id = t5_.story_id 
      LEFT JOIN tbl_like t6_  ON t5_.id = t6_.comment_id AND (t6_.creator_id = 3) 
      LEFT JOIN tbl_user t7_  ON t5_.creator_id = t7_.id 
      LEFT JOIN tbl_image t8_ ON t7_.avatar_id = t8_.id 
      LEFT JOIN tbl_location_city t9_  ON t0_.city_id = t9_.id 
      LEFT JOIN tbl_location_state t10_ ON t9_.state_id = t10_.id 
      LEFT JOIN tbl_location_country t11_ ON t10_.country_id = t11_.id 
      LEFT JOIN tbl_story t12_ ON t0_.parent_id = t12_.id 
      LEFT JOIN tbl_page t13_ ON t0_.page_id = t13_.id 
      LEFT JOIN tbl_page_type t14_ ON t13_.page_type_id = t14_.id 
      LEFT JOIN tbl_story_tag t25_  ON t0_.id = t25_.story_id 
      LEFT JOIN tbl_tag t15_ ON t15_.id = t25_.tag_id 
      LEFT JOIN tbl_story_linked_user_reference t16_ ON t0_.id = t16_.story_id 
      LEFT JOIN tbl_user t17_ ON t16_.user_id = t17_.id 
      LEFT JOIN tbl_image t18_ ON t17_.avatar_id = t18_.id 
      LEFT JOIN tbl_story t19_  ON t0_.id = t19_.parent_id 
      LEFT JOIN tbl_album t20_ ON t0_.parent_album_id = t20_.id 
      LEFT JOIN tbl_image t21_ ON t20_.id = t21_.album_id 
      LEFT JOIN tbl_image_linked_user t22_ ON t21_.id = t22_.image_id 
      LEFT JOIN tbl_user t23_ ON t22_.user_id = t23_.id 
      LEFT JOIN tbl_image t24_ ON t23_.avatar_id = t24_.id 
WHERE t0_.id IN 
        (SELECT 
          t26_.id 
        FROM tbl_story t26_ 
          INNER JOIN tbl_story_circle_visibility t28_ ON t26_.id = t28_.story_id 
          INNER JOIN tbl_circle t27_ ON t27_.id = t28_.circle_id 
          INNER JOIN tbl_user_circle_reference t29_ ON t27_.id = t29_.circle_id 
            AND (t29_.user_id = 3))
  AND t0_.is_draft = 0 
  AND t0_.type IN (0, 3, 2, 21) 
UNION
SELECT *
FROM
    tbl_story t0_ 
      LEFT JOIN tbl_user t1_ ON t0_.creator_id = t1_.id 
      LEFT JOIN tbl_image t2_  ON t1_.avatar_id = t2_.id 
      LEFT JOIN tbl_image t3_  ON t0_.id = t3_.story_id 
      LEFT JOIN tbl_like t4_ ON t0_.id = t4_.story_id AND (t4_.creator_id = 3) 
      LEFT JOIN tbl_comment t5_ ON t0_.id = t5_.story_id 
      LEFT JOIN tbl_like t6_  ON t5_.id = t6_.comment_id AND (t6_.creator_id = 3) 
      LEFT JOIN tbl_user t7_  ON t5_.creator_id = t7_.id 
      LEFT JOIN tbl_image t8_ ON t7_.avatar_id = t8_.id 
      LEFT JOIN tbl_location_city t9_  ON t0_.city_id = t9_.id 
      LEFT JOIN tbl_location_state t10_ ON t9_.state_id = t10_.id 
      LEFT JOIN tbl_location_country t11_ ON t10_.country_id = t11_.id 
      LEFT JOIN tbl_story t12_ ON t0_.parent_id = t12_.id 
      LEFT JOIN tbl_page t13_ ON t0_.page_id = t13_.id 
      LEFT JOIN tbl_page_type t14_ ON t13_.page_type_id = t14_.id 
      LEFT JOIN tbl_story_tag t25_  ON t0_.id = t25_.story_id 
      LEFT JOIN tbl_tag t15_ ON t15_.id = t25_.tag_id 
      LEFT JOIN tbl_story_linked_user_reference t16_ ON t0_.id = t16_.story_id 
      LEFT JOIN tbl_user t17_ ON t16_.user_id = t17_.id 
      LEFT JOIN tbl_image t18_ ON t17_.avatar_id = t18_.id 
      LEFT JOIN tbl_story t19_  ON t0_.id = t19_.parent_id 
      LEFT JOIN tbl_album t20_ ON t0_.parent_album_id = t20_.id 
      LEFT JOIN tbl_image t21_ ON t20_.id = t21_.album_id 
      LEFT JOIN tbl_image_linked_user t22_ ON t21_.id = t22_.image_id 
      LEFT JOIN tbl_user t23_ ON t22_.user_id = t23_.id 
      LEFT JOIN tbl_image t24_ ON t23_.avatar_id = t24_.id 
WHERE t0_.is_public = 1
  AND t0_.is_draft = 0 
  AND t0_.type IN (0, 3, 2, 21) 
ORDER BY t0_.created_at DESC
LIMIT 7 

【讨论】:

  • 不幸的是,我不能使用UNION,因为它在 Doctrine2 中不受支持
  • 哎哟。我马上就要控制框架了!
猜你喜欢
  • 2018-01-13
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 2015-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多