2011-01-12 15 views
1

このシナリオは、問題をより明確にするためにいくらか簡略化されています。 私の状況には、MySQLに一連のデータレコードが含まれています。MySQL GROUP BY/ORDER BYを最適化して交差を計算する

CREATE TABLE `records` (           
    `id` bigint(20) NOT NULL,              
    `property1` bigint(20) NOT NULL, 
    `property2` bigint(20) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `property1` (`property1`), 
    KEY `property2` (`property2`) 
); 

各レコードから、レコードデータに基づいて可変数のキー(ハッシュ)を生成して格納します。

CREATE TABLE `rkeys` (
    `rKey` bigint(20) NOT NULL, 
    `rId` bigint(20) NOT NULL, 
    KEY `rKey` (`rKey`), 
    KEY `rId` (`rId`), 
    FOREIGN KEY (`rId`) REFERENCES `records` (`id`) 
); 

(キー値がより均一鍵空間の上にそれらを配布するハッシュである。)

、例えば5万のレコード5000万個のキーがあってもよいです。

私がしようとしているのは、キーセットのファジー検索です。最も多くのキーを持つデータベースのレコードとレコードを照合します。結果は、レコードテーブルのプロパティに対してもフィルタリングする必要があります。

私はこのようになりますから取り組んできたクエリ:任意のキーを持つレコード数がかなり少ない場合に

SELECT rkeys.rId, records.property1, SUM(1) as score 
FROM rkeys, records 
WHERE 
    (rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14) AND 
    rkeys.rId = records.id AND 
    records.property1 = 1 AND 
    records.property2 = 2 
GROUP BY rId ORDER BY score DESC; 

パフォーマンスはOKです。問題は、数千のレコード(5000など)に表示されるキーを押した場合です。突然、GROUP BY/ORDER BYのパフォーマンスが崖から落ちます(クエリあたり15-20秒)。キーの配布をスムーズにすることは実際にはオプションではないことに注意してください。レコードのデータ自体は不均等に分散されています。

レコードの問題との結合は、問題の中核には見えません - 私は文脈のためだけにそれを含めています。

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: rkeys 
     type: index 
possible_keys: rKey 
      key: rKey 
     key_len: 8 
      ref: NULL 
     rows: 1 
     Extra: Using where; Using temporary; Using filesort 

が、私はこの作業をスピードアップするために、このテーブルまたはクエリを再構築することができる方法があります:

SELECT rId, SUM(1) as score 
FROM rkeys 
WHERE rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14 
GROUP BY rId ORDER BY score DESC; 

EXPLAIN出力:私がやりたいことすべてはこれがある場合、私はまだ同じ問題を参照してください?

答えて

0

これらのフィールドに非クラスタ化インデックス(インデックス)を追加しようとしましたか?主キー宣言がいくつかのSQLエンジンで行う暗黙的なクラスター化された索引作成を除いて、Keysがこれを自動的に過去に行ったのを見たことはありません。

+0

うーん、私の理解であったことが非プライマリインデックスMySQLがUNIQUEインデックスをクラスタ化するように「昇格」されていないか、行順に基づいて合成インデックスを生成しない限り、クラスタ化されていませんでした。 (http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.htmlを参照) – njudge

0

私はnoobのだけど、(RID RKEY)または(RID、RKEY)に複合インデックスを試してみてください

0

この

SELECT rId, Count(*) as score 
FROM rkeys 
WHERE rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14 
GROUP BY rId ORDER BY score DESC 

のようなものを試してみて、テーブル

にインデックスを追加
(rKey,rId) 

合計を置き換えても、大きな違いはありません。 (MSSQLのとにかく)

0

"キー値は、より均等にキースペースに分散させるためにハッシュされています"というのは、実際にはの不具合です。データがキャッシュされるには大きすぎると、ランダム性によって速度が低下します。

テーブルKeysは多くのマッピングテーブルとよく似ています。 Hereは、このようなテーブルのパフォーマンスを向上させるためのヒントです。そして、あなたのSELECTをスピードアップする可能性があります。

あなたSELECTこの「複合」と「カバー」インデックスと大幅に向上させる必要があります:MySQLで

INDEX(property1, property2, id) 

(。最適なインデックスを作成中More tips

関連する問題