2

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

SELECT a.* 
FROM entries a 
INNER JOIN entries_keywords b ON a.id = b.entry_id 
INNER JOIN keywords c ON b.keyword_id = c.id 
WHERE c.key IN ('wake', 'up') 
GROUP BY a.id 
HAVING COUNT(*) = 2

しかし、それは遅いです。処理を高速化するためにインデックスを最適に設計するにはどうすればよいですか?

編集 これは現在のスキーマです

CREATE TABLE `entries` (`id` integer PRIMARY KEY AUTOINCREMENT, `sha` text);
CREATE TABLE `entries_keywords` (`id` integer PRIMARY KEY AUTOINCREMENT, `entry_id` integer REFERENCES `entries`, `keyword_id` integer REFERENCES `keywords`);
CREATE TABLE `keywords` (`id` integer PRIMARY KEY AUTOINCREMENT, `key` string);
CREATE INDEX `entries_keywords_entry_id_index` ON `entries_keywords` (`entry_id`);
CREATE INDEX `entries_keywords_entry_id_keyword_id_index` ON `entries_keywords` (`entry_id`, `keyword_id`);
CREATE INDEX `entries_keywords_keyword_id_index` ON `entries_keywords` (`keyword_id`);
CREATE INDEX `keywords_key_index` ON `keywords` (`key`);

私はSqlite3を使用していますが、クエリは失敗しませんが、遅いです。

今、私は次のようなクエリです(各キーワードのサブクエリ):

select *
from (
    select *
    from (entries) e
    inner join entries_keywords ek on e.id = ek.entry_id
    inner join keywords k on ek.keyword_id = k.id
    where k.key = 'wake') e
inner join entries_keywords ek on e.id = ek.entry_id
inner join keywords k on ek.keyword_id = k.id
where k.key = 'up';

これははるかに高速ですが、キーワードがたくさんあると醜くなるので、正しく感じられません。

4

1 に答える 1

1

そのクエリに必要なキーインデックス

  • キーワード(キー)
  • entries_keywords(keyword_id、entry_id)
  • エントリ(id)

SELECT a。*は失敗するため、MySQLを使用している必要があります。
このステートメントに関する2番目のコメントの後で編集します。ここで失敗する理由 を指摘しておきます。select a.*これは、のせいですGROUP BY

説明すると、基準(WHERE)はc.keyにあるため、インデックスを作成する必要があります。
次に、b.keyword_idに対してJOINが上がります。b.entry_idを含めるインデックスを作成して、テーブルを検索する必要がないようにします。インデックスだけで必要な列をカバーできます。
最後に、a.id = b.entry_idがentrysテーブルに結合して戻るため、そのテーブルのIDにインデックスを付けます。

entries(id)すでに主キーである可能性が非常に高いですが、逆の方法でentries_keywordsインデックスを作成している可能性があります。この結合を満たすには機能しません。

于 2012-09-28T21:08:21.260 に答える