ブールフィールドのインデックスを作成することで、パフォーマンスの向上はありますか?


102

を含むクエリを記述しようとしていますWHERE isok=1。名前が示すように、isokはブールフィールドです(実際にはTINYINT(1) UNSIGNED、必要に応じて0または1に設定されるa )。

このフィールドのインデックスを作成すると、パフォーマンスが向上しますか?エンジン(この場合はInnoDB)は、インデックスのルックアップのパフォーマンスが向上しますか?


回答:


79

あんまり。あなたはそれを本のように考えるべきです。本に3種類の単語しかなく、それらすべてを索引付けすると、通常のページと同じ数の索引ページができます。

1つの値のレコードが比較的少ない場合は、パフォーマンスが向上します。たとえば、1000件のレコードがあり、そのうちの10件がTRUEの場合、次のように検索すると便利です。isok = 1

Michael Durrantが述べたように、書き込みも遅くなります。

編集:重複の可能性:ブールフィールドのインデックス作成

ここでは、インデックスがある場合でも、レコードが多すぎるとインデックスが使用されないことを説明します。 MySQLは= 1をチェックするときにインデックスを使用しませんが、= 0で使用します


4
「はい:2-いいえ:1」のように見えます。ここで誰かが間違っていますが、誰ですか?
Niet the Dark Absol 2012年

4
これは完全に正しいわけではありません。インデックスがないと、mySqlはテーブル全体をスキャンして関連する行を見つける必要があります。
ilanco、2012年

4
それ以外の場合は、インデックス全体をスキャンします。(ほとんどの場合それと同じくらい長いです)
マイケル・コペル

1
それは違いを生むことができます。インデックスを追加するだけでクエリの半分で実行時間を短縮できます。書き込みはまれであり、ペナルティを気にしないほど安価です。すべての場合と同様に、想定せずに測定してください(データベースは必ずしも論理的に期待どおりに動作しない場合があるためです)
Eelco

6
これは、TRUEとFALSEの間の均等な配分を前提としています。以下の@oucilで言及されているように、かなりまれなブール値を探している場合でも、しばらく時間がかかる可能性があります。常にインデックスを作成する必要があるとは言いませんが、ほとんどのデータベースエンジンでは、データとクエリの性質も重要だと思います。
mahemoff

117

私の経験では、このような質問を見ている人たちは私たちと同じボートにいるので、ブールフィールドのインデックス付けは無意味であると聞いたことがありますが...

約400万行のテーブルがあり、一度に約1000程度しかブールスイッチがフラグされません。これが検索対象です。ブールフィールドにインデックスを追加すると、クエリが桁違いに高速化され、約9秒以上から1秒未満になります。


はい、「理由」を明確に理解する必要がありますが、常に一緒に測定し、実際のデータセットでさまざまなことを試して、理論がdbエンジンの実際の動作と一致するかどうかを確認してください(驚かれることでしょう... )
Eelco 2015年

8
@Eelcoその通りですが、この場合、結果は実際には基本理論とよく一致しています。無視できるはずであるという基本的な考えは、検索に一致するアイテムに遭遇する可能性が約50%である場合にのみ意味があります。次に、100個の一致を見つけるには、DBは200個のアイテムを繰り返す必要があります。しかし、アイテムが1%の時間しか一致しない場合、10,000アイテムを繰り返す必要があります。
mahemoff

7
人々が実際にフィールドで物事を試し、哲学だけでなくパフォーマンスゲインフィードバックを与えるときが好きです。
Viktor

WHERE my_col > 0 代わりにmy_col = 1スピードを助けるように見える
アーロン

27

実際のクエリと、インデックスとクエリの組み合わせの選択性によって異なります。

ケースA:状態のみでWHERE isok = 1、他には何もありません。

SELECT *
FROM tableX
WHERE isok = 1
  • インデックスが十分に選択的である場合(たとえば、100万行あり、1k行のみisok = 1)、SQLエンジンはおそらくインデックス使用し、インデックスがない場合よりも高速になります。

  • インデックスが十分に選択的でない場合(たとえば、100万行あり、100k以上ある場合isok = 1)、SQLエンジンはおそらくインデックス使用せず、テーブルスキャンを実行します。

ケースB:状態WHERE isok = 1など:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

次に、他のどのインデックスを使用しているかによって異なります。インデックスanother_columnは、おそらくisok2つの値しか持たないインデックスよりも選択的です。(another_column, isok)または上のインデックスは(isok, another_column)さらに良いでしょう。


これは一番上より正解だと思います。データの分布も。
tyan

12

それはデータの分布に依存します。

厳密にタイプされた1000ページの本があり、私の本の単語は「はい」と「いいえ」だけが何度も繰り返され、ランダムに分布していたとします。「はい」のすべてのインスタンスを丸で囲むように依頼された場合、本の裏にある索引は役に立ちますか?場合によります。

「はい」と「いいえ」が半々ランダムに分布している場合、インデックスを調べても役に立ちません。インデックスを付けると、本がかなり大きくなります。とにかく、最初から始めて、各項目を調べるのではなく、「はい」のすべてのインスタンスを探して、それらを一周するように各ページを進めていきます。インデックスと、インデックスエントリから参照先のページへの参照を取得します。

しかし、たとえば、1000ページの本に「はい」のインスタンスが10個しかなく、それ以外はすべて何百万もない場合、インデックスを使用すると、「はい」の10個のインスタンスを見つけて循環させるのにかかる時間を大幅に節約できます。 。

データベースでも同じです。それが50:50の分布である場合、インデックスは役に立ちません-データベースエンジンは、データを最初から最後まで(フルテーブルスキャン)プラウするだけの方がよく、インデックスはデータベースを大きくします。書き込みと更新が遅い。しかし、(このスレッドのoucilのように)4000:1の分布のようなものである場合、探している項目の4000分の1であれば、インデックスシークによって大幅に高速化できます。


5

いいえ、通常はありません。

通常、フィールドは選択性/カーディナリティが高い場合に検索用にインデックスを付けます。ブールフィールドのカーディナリティは、ほとんどのテーブルで非常に低くなっています。また、書き込みが部分的に遅くなります。


3

実際、これは実行するクエリによって異なります。しかし、一般的にはそうです。また、他のタイプのフィールドにインデックスを付けることもできます。


2

はい、インデックスはパフォーマンスを向上させます。インデックスの有無にかかわらずEXPLAINの出力を確認してください。

ドキュメントから:

インデックスは、特定の列の値を持つ行をすばやく見つけるために使用されます。インデックスがない場合、MySQLは最初の行から始めて、関連する行を見つけるためにテーブル全体を読み取る必要があります。テーブルが大きいほど、コストが高くなります。テーブルに問題の列のインデックスがある場合、MySQLはすべてのデータを調べる必要なく、データファイルの中央でシークする位置をすばやく決定できます。

私はそれがインデックスがないだろうと言っても安全だと思うの減少だけそれから利益を持っているので、この場合には、パフォーマンスを。


2
インデックスはハードディスク上に大量のデータを提供し、書き込みを遅くするため、そこから得るだけではありません。
Michael Koper、2012年

1
正しいですが、この場合、TINYINT(1) UNSIGNED列、データのサイズは小さくなります。
ilanco

そして、追加された書き込みオーバーヘッドはおそらくかなり低い
Eelco

インデックス付きフィールドのサイズだけでなく、インデックスが指す行の数に応じてインデックスのサイズも大きくなりませんか?
poolie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.