0

次のようなスキーマを持つpostgres dbがあります

CREATE TABLE authors (
    id integer NOT NULL
);

CREATE TABLE posts (
    id integer NOT NULL,
    author_id integer,
    text text
);

CREATE TABLE comments (
    id integer NOT NULL,
    post_id integer,
    ordinal integer DEFAULT 0,
    author_id integer
);

特定の が与えられた場合、次のようなauthor_id20 件の投稿のバッチを選択できるようにしたいと考えています。

  1. その作者によるコメントのある投稿は含まれません。
  2. その作者による投稿ではありません。
  3. その投稿に対する最新の 10 件のコメントが含まれます。

ポイント#1はクエリ時間を殺していると思います。今までは、内部クエリを使用してその点を解決していました。

SELECT * from posts
WHERE posts.id NOT IN (
   SELECT posts.id FROM posts JOIN comments ON posts.id = comments.post_id)

データベースが大きくなるにつれて、このクエリは大幅に悪化しました。私は SQL が得意ではありません。これを行うより良い方法はありますか?それが役立つ/痛い場合は、ActiveRecordを使用しています。

4

3 に答える 3

0

提示されたクエリをデバッグする

あなたが提示したクエリは不必要に非効率的です。まず、サブクエリで冗長な JOIN を除外することで簡素化できます。

SELECT *
FROM   posts
WHERE  posts.id NOT IN (SELECT post_id FROM comments)

そして、これはセミアンチジョインとして、LEFT JOIN / IS NULLまたはNOT EXISTSセミアンチジョインで書き直すことができます。

SELECT *
FROM   posts p
WHERE  NOT EXISTS (SELECT 1 FROM comments c WHERE c.post_id = p.id)

完全なクエリ

あなたのポイント3.は不明です:

その投稿に対する最新の 10 件のコメントが含まれます。

それを無視すると、クエリは次のようになります。

SELECT *
FROM   posts p
WHERE  p.author_id <> $author_id -- "not a post by that author"
AND    NOT EXISTS (
   SELECT 1
   FROM   comments c
   WHERE  c.author_id = $author_id
   AND    c.post_id = p.id) -- exclude "post that has a comment by that author"
--  ORDER  BY ??undefined??, maybe id DESC
LIMIT  20

posts.author_id定義NOT NULLするか、次を使用する必要があります。

p.author_id IS DISTINCT FROM $author_id 

行数が多い場合、インデックスがパフォーマンスの鍵となります。主キーになると予想posts.idされるため、自動的にインデックスが作成されます。まだ持っていない場合は、この複数列インデックスを追加します。

CREATE INDEX comments_pa_idx ON comments (post_id, author_id);
于 2013-02-22T14:34:48.320 に答える
0

クエリをこれに置き換えます

SELECT * from posts p, comments c
WHERE posts.id <> c.posts.id;

それが役に立てば幸い

于 2013-02-22T13:09:32.293 に答える
0

私の経験では、「not in」は何よりもクエリ時間を殺します。代替手段は「存在しない」か、postgresql がこの構文をサポートしている場合です。

where somefield in 
(select somefield
 from etc
 except
 select somefield
 from etc)

例外の代わりにマイナスという言葉が使われることもあります。

于 2013-02-22T13:11:28.663 に答える