2009-07-07 3 views
9

カラムa、b、およびcを持つデータベーステーブルがあるとします。 3つの列すべてについてクエリを実行する予定ですが、特にどの列をクエリしているのかわかりません。 (このような)があり、インデックスが非常検索を高速化することをテーブルに十分な行がありますが、可能なインデックスのすべての順列を作るために間違って感じている:各パーミュテーションのインデックスを作成するよりも、複数の列をインデックスする良い方法はありますか?

a 
b 
c 
a, b 
a, c 
b, c 
a, b, c 

は、この問題に対処するためのより良い方法はありますか? (これは、行数を素早く減らすので、私はa、b、cのみをインデックスに登録することができますが、より良い方法があるかどうかは疑問です)

より具体的な例として、現実のデータでは、列は都市、州、および郵便番号です。また、私はMySQLデータベースを使用しています。

答えて

19

MS SQLでは、インデックス "a、b、c"はシナリオ "a"をカバーします。 "a、b";と "a、b、c"を入力します。したがって、次のインデックスだけが必要です。

a, b, c 
b, c 
c 

MySQLが同じように動作するかどうかはわかりませんが、私はそうするでしょう。

+7

これは正解です。 MySQLも同じように動作し、この手法は「左端接頭辞」と呼ばれます。 http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.htmlのMySQLマニュアルから: "テーブルに複数列のインデックスがある場合、インデックスの一番左の接頭辞はたとえば、(col1、col2、col3)に3列の索引がある場合、(col1)、(col1、col2)、および(col1、col2、col3)に索引検索機能があります。 " – zombat

+0

うーん、私はこれを知っていたはずです。 ;)非常に素晴らしい、私はこのショットを与えるだろう。 –

+1

また、a、cが必要かもしれませんが、クエリがどのように見えるかによって異なります。Andriyevが述べたORシナリオをカバーするために、個別のインデックスが必要な場合もあります。 –

1

作成するインデックスが多いほど、更新操作や削除操作中にパフォーマンスが低下します。インデックス自体が更新される可能性があるためです。

はい、複数列のインデックスを使用できます。

CREATE TABLE temp (
    id   INT NOT NULL, 
    a   INT NULL, 
    b   INT NULL, 
    c   INT NULL, 
    PRIMARY KEY (id), 
    INDEX ind1 (a,b,c), 
    INDEX ind2 (a,b) 
); 

ような何かインデックスすなわちIND1のこのタイプは確かに同様

SELECT * FROM temp WHERE a=2 AND b=3 AND c=4; 

ようなクエリのお手伝いをします、IND2は

SELECT * FROM temp WHERE a=2 AND b=3; 

のようなクエリのお手伝いをしますが、これらのインデックスは、」勝ちましたクエリが何らかのものである場合に使用されます。

SELECT * FROM temp WHERE a=2 OR b=3 OR c=4; 

ここでは、a、b、およびcに別々のインデックスが必要です。

このように多くのインデックスを使用するのではなく、私はJohnがa、b、cに索引を付けていることに同意します。さらに、複数の列の問合せが作業負荷に含まれていると感じる場合は、 。私は正しい、ジップだ場合

INDEX(郵便番号)

歓声

+0

この表はめったに更新されないので、更新が遅い場合は私には関係ありません。 –

1

あなたの列が実際に都市、州および郵便番号であることを考えると、私は、次のインデックスをお勧めしますコードは米国全域で複製されていないので、都市や州の情報をすべての郵便番号で同じ値にするため、インデックスにも追加するのは無意味です。たとえば、90210は、常にカリフォルニア州ロサンゼルスです。

INDEX(市(5))またはINDEX(市(5))、州)

これは、都市名の最初の5つの文字にだけインデックスです。多くの場合、これは、Stateが索引付けされていても有益なフィルタリングを提供できないほど具体的になります。たとえば、「Los A」は、ほぼ確実にカリフォルニア州ロサンゼルスの記録になります。アメリカには「Los A」から始まる小さな町があるかもしれませんが、記録があまりにも少なくて国家データのインデックスを乱雑にするほどの価値はありません。一方、いくつかの都市名は多くの州で出現しています(スプリングフィールドが気に入っています)ので、そのような場合は国家にも索引付けする方が良いです。自分のデータセットに最も適したインデックスを自分で判断する必要があります。疑いがある場合は、2番目の指標(都市と州)を使用します。

INDEX(州、sort_field

はかなり広範な指標である(恐らくNY単独レコードの30%を持っていますCA)。あなたが一度に、たとえば、30枚のレコードは、ユーザーにこの情報を表示する予定がある場合は、その後、あなたはそのクエリを効率的に行うために

... WHERE STATE = "NY" 
ORDER BY <sort_field> 
LIMIT <number>, 30 

で終わるクエリを持っているでしょう、あなたはでソート列を含める必要があり状態インデックス。したがって、姓で注文したページを表示している場合は、INDEX(州、姓(3))を使用してください。そうでなければ、MySQLはのすべてをの 'NY'それはあなたにあなたが望む30を与えることができます。

+2

郵便番号に関するあなたの情報は、厳密に正しいわけではありません。多くの郵便番号には複数の「受け入れ可能な地名」があります。たとえば、ハリウッドは実際の都市ではなくロサンゼルスの地区であるにもかかわらず、「ハリウッド、カリフォルニア州」は90028の受け入れ可能な地名です。 90028の「デフォルトの場所名」は、実際には「Los Angeles、CA」です。同様に、時には、2つの都市または2つの都市の部分が同じ郵便番号に入ることもあります。 各郵便番号に正確に1つの「デフォルトの地名」がありますが、ユーザーが入力したデータには依存することはできません。 – Geerad

+0

各郵便番号に2〜3個の地名が(ほとんどの場合)存在する限り、索引は正常です。 –

+0

パーセンテージはわかりませんが、私の郵便番号には4つの名前があります。そして私は4つも持っている別のものを知っています。 –

1

これはSQLクエリに依存します。

インデックス(a、b、c)は、すべての可能な等価条件のインデックスを使用するは(、、C B)指数(B、C、A)又はインデックスと異なる

4

    N列で、あなたは C([N/2], N)インデックスが必要になります、それは N!/([N/2]! * (N - [N/2])!)

    詳細な説明のための私のブログでこの記事を参照してくださいです0

  • Creating indexes

また、ロシアの数学者Egor Timoshenko更新:英語今)によって厳密な数学的proofを読むことができます。

一つは、しかし、次の技術を使用して以下のインデックスとまともなパフォーマンスを得ることができます:

をマージ

インデックス列col1col2col3は、このクエリ

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 
選択している場合

は、col1,col2およびcol3に3つの別個のインデックスを使用することができ、個別に各条件に合致ROWID年代を選択し、それらはのように、彼らの交差点を見つける:

PostgreSQLは、右のクエリの実行中にメモリ内の一時的なビットマップ索引を構築することができ

SELECT * 
FROM (
     SELECT rowid 
     FROM mytable 
     WHERE col1 = :value1 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col2 = :value2 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col3 = :value3 
     ) mo 
JOIN mytable mi 
ON  mi.rowid = mo.rowid 

ビットマップ索引。

ビットマップインデックスは、非常にコンパクトな連続ビット配列です。

アレイに設定された各ビットは、対応するtidを表から選択する必要があることを示します。

このような索引は、1G行の表の一時記憶域のうち、128Mを使用できます。

次のクエリ:

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 

最初(0, 0)乃至S「のそれはすべてtidを取るのに十分な大きさである(表中のS」のすべての可能なtidをカバーするのに十分な大きさゼロで満たされたビットマップを割り当てます最後のtid、紛失していないことを考慮に入れてtid)。

次に、最初のインデックスを探し、最初の条件を満たす場合はビットを1に設定します。

次に、1の第2の条件を満たすビットであるANDをスキャンします。これにより、両方の条件を満たすビットに対してのみ、1のままになります。

3番目のインデックスと同じです。

最後に、ビットセットに対応するtidの行を選択するだけです。

tidは順番に取得されるので、非常に効率的です。

関連する問題