2

MySQL を使用して wiki に順方向インデックスを作成しています。クエリでパフォーマンスの問題が発生しており、スキーマまたはクエリを最適化するための助けを期待しています

データベースは約 1GB で、3 つのテーブルがあります。

  • fi_page は 800k wiki ページのテーブルです
  • fi_keyword は 70k キーワードのテーブルです

    CREATE TABLE `fi_keyword` (  
      `id` int(11) NOT NULL AUTO_INCREMENT,  
      `keyword` varchar(100) NOT NULL,  
      PRIMARY KEY (`id`),  
      UNIQUE KEY `keyword` (`keyword`)  
    );
    
  • fi_titlekeywordlink は、キーワードを wiki ページにリンクする 600 万のエントリを含むテーブルです

    CREATE TABLE `fi_titlekeywordlink` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `keyword_id` int(11) NOT NULL,
      `page_id` int(11) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `fi_titlekeywordlink_a6434082` (`keyword_id`),
      KEY `fi_titlekeywordlink_c2d3d2bb` (`page_id`),
      CONSTRAINT `keyword_id_refs_id_67197756` FOREIGN KEY (`keyword_id`) REFERENCES `fi_keyword` (`id`),
      CONSTRAINT `paper_id_refs_id_705ddf03` FOREIGN KEY (`page_id`) REFERENCES `fi_page` (`id`)
    );
    

「豊富な検索用語」の検索を次のようなSQLクエリに変換しています

    select p.*
      from
        fi_keyword as k0, fi_titlekeywordlink as l0,
        fi_keyword as k1, fi_titlekeywordlink as l1,
        fi_keyword as k2, fi_titlekeywordlink as l2,
        fi_keyword as k3, fi_titlekeywordlink as l3,
        fi_page as p
      where
        k0.keyword = e and k0.id = l0.keyword_id and p.id = l0.paper_id
        and k1.keyword = 'search' and k1.id = l1.keyword_id and p.id = l1.paper_id
        and k2.keyword = 'terms' and k2.id = l2.keyword_id and p.id = l2.paper_id
        and k3.keyword = 'galore' and k3.id = l3.keyword_id and p.id = l3.paper_id
      limit 1,10

ただし、これは私の MBP で実行するのに約 0.5 秒かかります。スキーマまたはクエリを変更して、この種の操作を高速化する方法について何か提案はありますか? この場合、別の検索サーバーを使用することはできません。フォワード インデックスは MySQL で実行する必要があります。ありがとうございました。

4

1 に答える 1

2

挿入パフォーマンスを犠牲にしてid、両方のテーブルからサロゲート主キー列を削除し、 keywordfi_keyword の列に主キー インデックスを作成し、( keyword_id, page_id) を fi_titlekeywordlink の主キー インデックスとして作成することができます。

InnoDB を使用している場合、主キーはクラスター化されたインデックスであるため、はるかに高速です。

この変更を行わなくても、fi_titlekeywordlink で ( keyword_id, page_id) の複合 (複数列) インデックスを使用すると、fi_titlekeywordlink でカバリング インデックス (MySQL がテーブル データにアクセスする必要がない) があるため、パフォーマンスが向上します。これは、MySQL サーバーにメモリ内のすべてのインデックスに適合する十分な RAM があり、MySQL サーバーが十分な RAM を使用できるように構成されていることを前提としています (構成変数はMyISAMInnoDBで異なります)。

場合によっては、暗黙的な JOIN が複雑になりすぎて、MySQL が適切に最適化できないことがあります。JOINおよびを使用して明示的な ANSI 標準結合を使用してクエリを書き直すことも検討する必要がありますON

簡潔にするために書いただけかもしれませSELECT p.*んが、必要な列だけを選択して、不要なデータを返さないようにしてください。必要な列のみを返すことで、作業負荷が軽減されます。

また、LIMIT 句の最初の行は 0 であるためLIMIT 1, 10、最初の行をスキップします。LIMIT 0, 10最初の 10 行を取得するために使用します。

于 2012-05-10T14:13:24.797 に答える