0

クエリのパフォーマンスを向上させ、selectステートメントでのメモリの損失を最小限に抑えたい場合は、データベースにブール値を挿入するための最良のソリューションは何ですか。

例:36個のフィールドを持つテーブルがあり、そのうち30個はブール値(0または1)であり、真の値を持つブールフィールドを使用してレコードを検索する必要があります。

SELECT * FROM `myTable`
WHERE 
    `field_5th` = 1 
    AND `field_12th` = 1 
    AND `field_20` = 1 
    AND `field_8` = 1

解決策はありますか?

4

2 に答える 2

1

ブール値またはフラグを保存する場合、基本的に 3 つのオプションがあります。

  1. 個々の列

これは、上記の例に反映されています。利点は、ルックアップに最も頻繁に使用する予定のフラグにインデックスを付けることができることです。欠点は、これがより多くのスペースを占有することです (割り当て可能な最小列サイズは 1 バイトであるため)。

ただし、列名が実際にfield_20、field_21などになる場合、これは絶対に行くべきではありません。番号付きの列は、他の 2 つの方法のいずれかを使用する必要があることを示しています。

  1. ビットマスク

上で提案したように、単一の整数列に複数の値を格納できます。BIGINT 列は、最大 64 個の可能なフラグを提供します。

値は次のようになります。 UPDATE table SET flags=b'100'; UPDATE テーブル SET flags=b'10000';

次に、フィールドは次のようになります: 10100

これは、2 つのフラグ値が設定されていることを表します。特定のフラグ値セットを照会するには、次のようにします。

SELECT フラグ FROM テーブル WHERE フラグ & b'100';

これの利点は、フラグがスペース的に非常にコンパクトになることです。欠点は、フィールドにインデックスを配置できないことです。これにより、特定のフラグを検索するパフォーマンスが向上します。

  1. 一対多の関係

これは、別のテーブルを作成する場所であり、そこにある各行には、リンクされている行の ID とフラグがあります。

CREATE TABLE main ( main_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, );

CREATE TABLE フラグ ( main_id INT UNSIGNED NOT NULL, name VARCHAR(16) );

次に、複数の行をフラグ テーブルに挿入します。

利点は、ルックアップにインデックスを使用できることと、スキーマを変更せずに行ごとに任意の数のフラグを設定できることです。これは、ほとんどの行に値セットがないスパース値に最適です。すべての行にすべてのフラグを定義する必要がある場合、これはあまり効率的ではありません。

パフォーマンスの比較については、私がトピックについて書いたブログ投稿を読むことができます: Set Performance Compare

また、どれが「最高」であるかを尋ねるとき、それは非常に主観的な質問です. 何が得意?それはすべて、データがどのように見えるか、要件が何であるか、およびどのようにクエリを実行するかによって異なります。

次のようなクエリを実行する場合は、次のことに注意してください。 SELECT * FROM table WHERE some_flag=true

インデックスは、その値が設定されている行がほとんどない場合にのみ役立ちます。テーブル内のほとんどの行に some_flag=true がある場合、mysql はインデックスを無視し、代わりにフル テーブル スキャンを実行します。

于 2012-07-01T18:18:10.567 に答える
0

何行のデータに対してクエリを実行していますか? ブール値を整数値に格納し、ビット演算を使用してそれらをテストできます。インデックス可能ではありませんが、ストレージは非常によく詰め込まれています。インデックスで TINYINT フィールドを使用すると、使用するインデックスが 1 つ選択され、そこからスキャンされます。

于 2012-07-01T17:30:08.707 に答える