0

私はこのクエリを持っています:

SELECT p.id, r.status, r.title
FROM page AS p
    INNER JOIN page_revision as r ON r.pageId = p.id AND (
        r.id = (SELECT MAX(r2.id) from page_revision as r2 WHERE r2.pageId = r.pageId AND r2.status = 'active')
        OR r.id = (SELECT MAX(r2.id) from page_revision as r2 WHERE r2.pageId = r.pageId)
    )

これは、アクティブなリビジョンがない場合を除き、各ページとそれぞれの最新のアクティブなリビジョンを返します。アクティブなリビジョンがない場合は、単に最新のリビジョンを返します。

これを最適化してパフォーマンスや一般的な読みやすさを向上させる方法はありますか? 今のところ問題はありませんが、心配なのは、これが実稼働環境 (大量のページが存在する可能性がある環境) に入ると、パフォーマンスが低下することです。

また、私が知っておくべき明らかな問題はありますか? サブクエリの使用は常に私を悩ませますが、私の知る限り、サブクエリなしではこれを行うことはできません.

注:
条件が WHERE 句ではなく JOIN にある理由は、他のクエリ (これと同じロジックが使用されている場合) で、「サイト」テーブルから「ページ」テーブルに LEFT JOIN しているためです。まだサイトを返してほしい。

ジャック

編集: MySQLを使用しています

4

4 に答える 4

0

MS SQL 2005+Oracle: _

SELECT p.id, r.status, r.title
FROM (
  SELECT p.*, r,*,
         ROW_NUMBER() OVER (PARTITION BY p.pageId ORDER BY CASE WHEN p.status = 'active' THEN 0 ELSE 1 END, r.id DESC) AS rn
  FROM page AS p, page_revision r
  WHERE r.id = p.pageId
  ) o
WHERE rn = 1

外部クエリからの式は定数と見なされMySQLないため、サブクエリは を使用できないため、これが問題になる可能性があります。INDEX RANGE SCAN

これらのインデックスを使用するには、2 つのインデックスと、最後のページ リビジョンを返す関数を作成する必要があります。

CREATE INDEX ix_revision_page_status_id ON page_revision (page_id, id, status);

CREATE INDEX ix_revision_page_id (page_id, id);

CREATE FUNCTION `fn_get_last_revision`(input_id INT) RETURNS int(11)
BEGIN
  DECLARE id INT;
  SELECT r_id
  INTO id
  FROM (
    SELECT r.id
    FROM page_revisions
    FORCE INDEX (ix_revision_page_status_id)
    WHERE page_id = input_id
      AND status = 'active'
    ORDER BY id DESC 
    LIMIT 1
    UNION ALL
    SELECT r.id
    FROM page_revisions
    FORCE INDEX (ix_revision_page_id)
    WHERE page_id = input_id
    ORDER BY id DESC 
    LIMIT 1
  ) o
  LIMIT 1;
  RETURN id;
END;

SELECT po.id, r.status, r.title
FROM (
  SELECT p.*, fn_get_last_revision(p.page_id) AS rev_id
  FROM page p
) po, page_revision r
WHERE r.id = po.rev_id;

これにより、インデックスを効率的に使用して、ページの最後のリビジョンを取得できます。

PSステータスにコードを使用0し、アクティブに使用する場合は、2番目のインデックスを削除してクエリを簡素化できます。

于 2009-02-18T12:07:08.870 に答える
0

あなたの問題は、この質問で説明されている特定のケースです。

標準の ANSI SQL を使用して得られる最高のものは次のようです。

SELECT p.id, r.status, r.title
FROM page AS p
INNER JOIN page_revision as r ON r.pageId = p.id 
AND r.id = (SELECT MAX(r2.id) from page_revision as r2 WHERE r2.pageId = r.pageId)

他のアプローチも利用できますが、使用しているデータベースによって異なります。MySQL でこれを大幅に改善できるかどうかはよくわかりません。

于 2009-02-18T12:10:40.470 に答える