استعلامات بطيئة تم العثور عليها في سجل قاعدة البيانات

أقوم بتشغيل الاختبارات في Discourse وأجد بعض الاستعلامات غير الفعّالة في سجل الاستعلامات على النحو التالي:

  1. استخدام DISTINCT غير ضروري يبطئ الاستعلام site_settings_controller.rb#L165 كما يلي:
SELECT 
  DISTINCT users.id 
FROM 
  "users" CROSS 
  JOIN categories c 
  LEFT JOIN category_users cu ON users.id = cu.user_id 
  AND c.id = cu.category_id 
WHERE 
  (
    c.id = '3613'
    AND cu.notification_level IS NULL
  )

عند تحديد قيم لـ categories.id و notification_level، وبسبب وجود UNIQUE (category_id, user_id) في جدول category_users و PRIMARY KEY(id) في جدول categories، فإن كل من عمليات الربط المتقاطع (cross join) والربط الأيسر (left join) لن تُنتج سجلات مكررة، مما يعني أنه يمكننا إزالة DISTINCT لتسريع الاستعلام كما هو موضح أدناه:
استغرق الاستعلام المحسّن 4532166 نانوثانية (تحسين بنسبة 30%)

  1. استخدام DISTINCT غير ضروري في الاستعلام الفرعي يبطئ الاستعلام search.rb#L523
SELECT 
  "posts".* 
FROM 
  "posts" 
  JOIN (
    SELECT 
      *, 
      row_number() over() row_number 
    FROM 
      (
        SELECT 
          topics.id, 
          min(posts.post_number) post_number 
        FROM 
          "posts" 
          INNER JOIN "post_search_data" ON "post_search_data"."post_id" = "posts"."id" 
          INNER JOIN "topics" ON "topics"."id" = "posts"."topic_id" 
          AND ("topics"."deleted_at" IS NULL) 
          LEFT JOIN categories ON categories.id = topics.category_id 
        WHERE 
          ("posts"."deleted_at" IS NULL) 
          AND "posts"."post_type" IN (1, 2, 3) 
          AND (topics.visible) 
          AND (
            topics.archetype <> 'private_message'
          ) 
          AND (
            topics.id IN (
              SELECT 
                DISTINCT(tt.topic_id) 
              FROM 
                topic_tags tt 
              WHERE 
                tt.tag_id in (
                  SELECT 
                    tag_id 
                  FROM 
                    tag_group_memberships 
                  WHERE 
                    tag_group_id = 504
                )
            )
          ) 
          AND (
            categories.id NOT IN (
              SELECT 
                categories.id 
              WHERE 
                categories.search_priority = 1
            )
          ) 
          AND (
            (categories.id IS NULL) 
            OR (NOT categories.read_restricted)
          ) 
        GROUP BY 
          topics.id 
        ORDER BY 
          MAX(posts.created_at) DESC 
        LIMIT 
          6 OFFSET 0
      ) xxx
  ) x ON x.id = posts.topic_id 
  AND x.post_number = posts.post_number 
WHERE 
  ("posts"."deleted_at" IS NULL) 
ORDER BY 
  row_number

استخدام DISTINCT(tt.topic_id) زائد عن الحاجة ويمكن إزالته لتسريع الاستعلام كما هو موضح أدناه:
يمكن أن يحسّن أداء هذا الاستعلام من 12655768 إلى 5005154 (تحسين بنسبة 60%)

  1. استخدام DISTINCT غير ضروري في الاستعلام الفرعي يبطئ الاستعلام [search.rb#L642]
SELECT 
  "posts".* 
FROM 
  "posts" 
  JOIN (
    SELECT 
      *, 
      row_number() over() row_number 
    FROM 
      (
        SELECT 
          topics.id, 
          posts.post_number 
        FROM 
          "posts" 
          INNER JOIN "post_search_data" ON "post_search_data"."post_id" = "posts"."id" 
          INNER JOIN "topics" ON "topics"."id" = "posts"."topic_id" 
          AND ("topics"."deleted_at" IS NULL) 
          LEFT JOIN categories ON categories.id = topics.category_id 
        WHERE 
          ("posts"."deleted_at" IS NULL) 
          AND "posts"."post_type" IN (1, 2, 3) 
          AND (topics.visible) 
          AND (
            topics.archetype <> 'private_message'
          ) 
          AND (
            topics.category_id IN (3715)
          ) 
          AND (
            topics.id IN (
              SELECT 
                DISTINCT(tt.topic_id) 
              FROM 
                topic_tags tt, 
                tags 
              WHERE 
                tt.tag_id = tags.id 
                AND lower(tags.name) IN ('lunch')
            )
          ) 
          AND (
            (categories.id IS NULL) 
            OR (NOT categories.read_restricted)
          ) 
        ORDER BY 
          posts.like_count DESC 
        LIMIT 
          6 OFFSET 0
      ) xxx
  ) x ON x.id = posts.topic_id 
  AND x.post_number = posts.post_number 
WHERE 
  ("posts"."deleted_at" IS NULL) 
ORDER BY 
  row_number

مشابه للسابق (مع اختلاف في كود المصدر)، فإن استخدام DISTINCT(tt.topic_id) زائد عن الحاجة ويمكن إزالته لتسريع الاستعلام:
يمكن أن يحسّن أداء هذا الاستعلام من 23659762 إلى 21030593 (تحسين بنسبة 10%).