0

そこで、元の記事 ($id 変数で提供) と共通するタグの数に基づいて「関連記事」を検索する、この超大規模なクエリがあります。実際のクエリが重要かどうかはわかりませんが、ここではジャスティン ケースです。

現在、ライブ プロジェクトで実際にプロシージャを使用したことはありませんが、MySQL エンジンが毎回コードを解釈する必要がないため、より高速になるはずだと読んだことがあります。しかし、これと同じコードをプロシージャに入れて呼び出したところ、実行時間は平均で約 450 倍長くなりました。

なんで?複数の行を返すからですか?手順はそれで悪臭を放ちますか?プロシージャで入力変数を使用する必要があるためですか? 450は束です!

SELECT a.id, a.image, a.title, a.excerpt, a.permalink, COUNT(rel.category_id) AS n
  FROM articles AS a
  JOIN category_relations AS rel ON rel.article_id = a.id
  JOIN categories AS c ON rel.category_id = c.id
 WHERE rel.category_id IN (SELECT category_id 
                             FROM category_relations 
                            WHERE article_id = {$id})
   AND a.id != {$id}
   AND c.type = 1
GROUP BY rel.article_id
ORDER BY n DESC, publish_date DESC
   LIMIT 10

プロシージャの作成に使用されるコード:

DROP PROCEDURE IF EXISTS get_related_articles;
DELIMITER //
CREATE PROCEDURE get_related_articles(IN id INT)
BEGIN
   SELECT   a.id, a.image, a.title, a.excerpt, a.permalink, COUNT(rel.category_id) AS n
   FROM     articles AS a
    JOIN  category_relations AS rel ON rel.article_id = a.id
    JOIN  categories AS c ON rel.category_id = c.id
   WHERE    rel.category_id IN ( SELECT category_id FROM category_relations WHERE article_id = id)
    AND   a.id != id
    AND   c.type = 1
   GROUP BY rel.article_id
   ORDER BY n DESC, publish_date DESC
   LIMIT    10;
END //
DELIMITER ;
4

2 に答える 2

1

MySQL の現実世界へようこそ! あるクエリが別のクエリよりも長く実行される理由を説明するのが非常に難しい場合があります。しかし、あなたの場合、答えはここにあります:

MySQL は、クエリがストアド プロシージャから呼び出された場合にキャッシュを使用しません。

于 2013-03-07T09:03:19.067 に答える
0

遅延については肯定的ではありませんが、IN SUBSELECTS 自体が高くつく可能性があります。現在サブセレクトになっているものに結合することを考えましたか? また、articles テーブルがクエリのベースであり、a.id = rel.article_id であるため、インデックス経由で利用できる場合は、「a.id」でグループ化する方がよい場合があります。

SELECT 
      a.id, 
      a.image, 
      a.title, 
      a.excerpt, 
      a.permalink
   FROM 
      articles AS a
         JOIN category_relations AS rel 
            ON a.id = rel.article_id 
            JOIN categories AS c 
               ON rel.category_id = c.id
               AND c.type = 1
            JOIN (SELECT category_id 
                     FROM admin_category_relations 
                     WHERE article_id = {$id} ) RelByArticle
               on rel.category_id = RelByArticle.category_id
   WHERE 
      a.id != {$id}
   GROUP BY 
      a.id
   ORDER BY 
      n DESC, 
      publish_date DESC
   LIMIT 10
于 2013-03-07T03:24:42.603 に答える