質問

次のクエリは 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

...フィールドのインデックスが作成されているかどうか?

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

役に立ちましたか?

解決

アップデート:

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


SELECT * FROM table WHERE field & number = number

SELECT * FROM table WHERE field | number = number

このインデックスは次の 2 つの方法で効果を発揮します。

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

上記のクエリのどちらの条件も 検索可能な, 、これは範囲スキャンに使用されないインデックスです (現在の条件で)。

ただし、ポイント 1 は今でも保持されており、インデックスは役立つ可能性があります。

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

インデックスがある場合 ( 4-バイトキー、 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 最後に設定されていないほど良いです。

他のヒント

私は、オプティマイザはその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); 

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top