6

次のクエリはMySQLで効果的ですか?

SELECT * FROM table WHERE field & number = number; 
# to find values with superset of number's bits

SELECT * FROM table WHERE field | number = number; 
# to find values with subset of number's bits

...フィールドのインデックスが作成されている場合は?

そうでない場合、それをより速く実行する方法はありますか?

4

3 に答える 3

7

アップデート:

パフォーマンスの詳細については、ブログの次のエントリを参照してください。


SELECT * FROM table WHERE field & number = number

SELECT * FROM table WHERE field | number = number

このインデックスは、次の2つの方法で効果的です。

  1. 初期のテーブルスキャンを回避するため(比較する値がインデックス自体に含まれているため)
    • 調べる値の範囲を制限します。

上記のクエリのどちらの条件もsargableではありません。これは、インデックスが範囲スキャンに使用されないことです(現在の条件では)。

ただし、ポイント1は引き続き保持されるため、インデックスが役立つ場合があります。

たとえば、テーブル100に平均で1行あたりのバイト数と1,000,000レコードが含まれている場合、テーブルスキャンではデータをスキャンする必要があり100 Mbます。

インデックス(4-byteキー、 -byte行ポインター、および内部オーバーヘッドを含む)がある場合、フィルターが成功すると、クエリはデータとテーブルからの追加データ6のみをスキャンする必要があります。10 Mb

  • 条件が選択的でない場合(条件に一致する可能性が高い場合)、テーブルスキャンはより効率的です。
  • 条件が選択的である場合(条件に一致する可能性が低い場合)、インデックススキャンはより効率的です。

これらのクエリは両方とも、インデックス全体をスキャンする必要があります。

ただし、クエリを書き直すANDことで、インデックスの範囲からもメリットを得ることができます。

この状態:

field & number = number

セットの最上位ビットもnumber設定されている場合にのみ、フィールドに一致することができfieldます。

そして、この追加の条件をクエリに指定する必要があります。

SELECT  *
FROM    table
WHERE   field & number = number
        AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)

これは、粗いフィルタリングの範囲と細かいフィルタリングの条件を使用します。

number最後に未設定のビットが多いほど良いです。

于 2009-09-28T15:34:39.437 に答える
1

オプティマイザーがそれを理解するのではないかと思います...

たぶん、これらのクエリでEXPLAINを呼び出して、私の悲観的な推測を確認することができます。(もちろん、クエリプランの決定の多くは、特定のデータベースの特定のインスタンスに基づいていることを思い出してください。つまり、可変量のデータや、異なる統計プロファイルを持つデータだけが、異なるプランを生成する可能性があります)。

テーブルにかなりの量の行があり、「ビット単位」の基準が十分に選択的であると仮定すると、IN構文(またはJOIN)を使用してクエリを書き直すことにより、すべての単一行でビット演算を回避するときに可能な最適化が実現されます。 )。

そのようなもの(概念的、つまりテストされていない)

CREATE TEMPORARY TABLE tblFieldValues
  (Field INT);

INSERT INTO tblFieldValues
   SELECT DISTINCT Field
   FROM table;

-- SELECT * FROM table WHERE field | number = number; 
-- now becomes
SELECT * 
FROM table t
WHERE field IN 
    (SELECT Field 
     FROM tblFieldValues 
     WHERE field | number = number); 

このようなアプローチのすべての利点は、さまざまなユースケースで評価する必要があります(それ以外の場合は、直接の「WHEREフィールド|数値=数値」アプローチが十分に効率的であるため、すべてテーブル内の行数がかなり多くなります)。これは大幅に高速になる可能性があります。「tblFieldValues」を毎回再作成する必要がない場合は、さらにゲインを上げることができます。もちろん、このテーブルを効率的に作成することは、元のテーブルのフィールドにインデックスを付けることを意味します。

于 2009-09-21T23:27:47.787 に答える
0

私はこれを自分で試しましたが、ビット単位の操作では、Mysqlが「フィールド」列のインデックスを使用するのを防ぐのに十分ではありません。ただし、インデックスのフルスキャンが行われている可能性があります。

于 2009-09-28T15:28:48.807 に答える