31

私のプラットフォーム:

PHP & MySQL

私の状況:

テーブルの列の 1 つにユーザー選択の値を格納する必要がある状況に遭遇しました。今、私のオプションは次のとおりです。

  1. 列を char(1) として宣言し、値を 'y' または 'n' として格納します。
  2. または、列を tinyint(1) として宣言し、値を 1 または 0 として保存します
  3. そのように宣言されたこの列は、アプリケーション内で使用するために索引付けすることもできます。

私の質問:

だから私は知りたかったのですが、上記の2つのタイプのどれですか:

  1. その列にアクセスすると、クエリ速度が速くなります (簡単にするために、他のクエリを混在させたり、他の列にアクセスしたりすることは避けてください)。

  2. データを保存およびアクセスする最も効率的な方法とその理由は?

  3. 列に索引が付けられている場合とそうでない場合、アクセス速度はどのように異なりますか?

私の理解では、char(1) と tinyint(1) は 1 バイトのスペースしか占有しないため、この場合、ストレージ スペースは問題になりません。あとはアクセス速度ですね。私の知る限り、数値インデックスは何よりも高速で効率的です。しかし、ここでのケースは判断が難しいと思います。これに関するあなたの経験をぜひお聞きしたいと思います。

前もって感謝します。

4

8 に答える 8

43
                       Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1)     207/s                --            -1%                  -20%
insert char(1)        210/s                1%             --                  -19%
insert enum('y', 'n') 259/s               25%            23%                    --
                       Rate insert char(1) insert tinyint(1) insert enum('y', 'n')
insert char(1)        221/s             --               -1%                  -13%
insert tinyint(1)     222/s             1%                --                  -13%
insert enum('y', 'n') 254/s            15%               14%                    --
                       Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1)     234/s                --            -3%                   -5%
insert char(1)        242/s                3%             --                   -2%
insert enum('y', 'n') 248/s                6%             2%                    --
                       Rate insert enum('y', 'n') insert tinyint(1) insert char(1)
insert enum('y', 'n') 189/s                    --               -6%           -19%
insert tinyint(1)     201/s                    7%                --           -14%
insert char(1)        234/s                   24%               16%             --
                       Rate insert char(1) insert enum('y', 'n') insert tinyint(1)
insert char(1)        204/s             --                   -4%               -8%
insert enum('y', 'n') 213/s             4%                    --               -4%
insert tinyint(1)     222/s             9%                    4%                --

ほとんどの場合、enum('y', 'n')挿入する方が速いようです。

                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        188/s             --               -7%                   -8%
select tinyint(1)     203/s             8%                --                   -1%
select enum('y', 'n') 204/s             9%                1%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        178/s             --              -25%                  -27%
select tinyint(1)     236/s            33%                --                   -3%
select enum('y', 'n') 244/s            37%                3%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        183/s             --              -16%                  -21%
select tinyint(1)     219/s            20%                --                   -6%
select enum('y', 'n') 233/s            27%                6%                    --
                       Rate select tinyint(1) select char(1) select enum('y', 'n')
select tinyint(1)     217/s                --            -1%                   -4%
select char(1)        221/s                1%             --                   -2%
select enum('y', 'n') 226/s                4%             2%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        179/s             --              -14%                  -20%
select tinyint(1)     208/s            17%                --                   -7%
select enum('y', 'n') 224/s            25%                7%                    --

選択もそうenumです。コードはここにあります

于 2010-01-08T14:01:55.250 に答える
35

で列を作成する必要があると思いますENUM('n','y')。Mysql はこの型を最適な方法で保存します。また、許可された値のみをフィールドに保存するのにも役立ちます。

ENUM('no','yes')また、パフォーマンスに影響を与えずに、より人間にやさしくすることもできます。文字列'no'とは定義'yes'ごとに 1 回だけ格納されるためです。ENUMMysql は、行ごとに値のインデックスのみを保存します。

ENUM列によるソートについても注意してください。

ENUM 値は、列の指定で列挙メンバーがリストされた順序に従ってソートされます。(つまり、ENUM 値はインデックス番号に従ってソートされます。) たとえば、ENUM('a', 'b') の場合、'a' は 'b' の前にソートされますが、ENUM の場合、'b' は 'a' の前にソートされます。 ('b'、'a')。

于 2010-01-07T20:43:21.280 に答える
11

tinyint を使用する方がより標準的な方法であり、フィールドの値をより簡単に確認できます。

// Using tinyint 0 and 1, you can do this:
if($row['admin']) {
    // user is admin
}

// Using char y and n, you will have to do this:
if($row['admin'] == 'y') {
    // user is admin
}

私は MySQL の内部動作の専門家ではありませんが、整数フィールドの取得と並べ替えは文字フィールドよりも速いと直感的に感じています ('a' > 'z' は 0 > 1 よりも作業が多いと感じています)。 、および 0 と 1 が標準のオン/オフフラグであるコンピューティングの観点からは、はるかに親しみを感じているようです。そのため、整数のストレージはより優れているように見え、より快適になり、コード ロジックでの使用が容易になります。0/1 は私にとって明確な勝者です。

また、ある程度、これは MySQL の公式の立場でもあり、ドキュメントからもわかる場合があります。

BOOL、BOOLEAN: これらの型は TINYINT(1) と同義です。ゼロの値は false と見なされます。ゼロ以外の値は true と見なされます。

MySQL が TINYINT(1) を BOOLEAN と同一視するところまで進んでいる場合、それが進むべき道のように思えます。

于 2010-01-07T20:43:06.293 に答える
4

それを確実に知るには、ベンチマークする必要があります。または、プロジェクト全体のより大きな視点では、おそらくそれほど重要ではないことを知っています.

Char 列にはエンコーディングと照合順序があり、それらを比較するとエンコーディング間の不要な切り替えが必要になる可能性があるため、int の方が高速になると思います。同じ理由で、int 列のインデックスの更新も高速だと思います。しかし、繰り返しますが、それほど重要ではありません。

CHAR選択した文字セットとテーブル オプションによっては、1 バイト以上を占める場合があります。一部の文字はエンコードに 3 バイトかかる場合があるため、MySQL は、 と のみを使用する場合でも、そのスペースを予約することがyありnます。

于 2010-01-07T20:46:17.810 に答える
3

二人はとても近くにいるので、それは問題ではありません。SO でこの質問をしなければならないと感じたら、最適化しすぎています。最も論理的な意味を持つものを使用してください。

于 2010-01-07T20:48:07.547 に答える
1

MySQL でテーブルを作成するときに列の型としてBOOLまたはの型を指定すると、列の型が として作成されます。おそらく、これは 2 つの中で高速です。BOOLEANTINYINT(1)

ドキュメンテーション

また:

将来の MySQL リリースでは、標準 SQL に従って、完全なブール型処理を実装する予定です。

于 2010-01-07T20:50:16.850 に答える
1

私の推測では、文字列処理のオーバーヘッド (照合、空白など) がないため、TINYINT のインデックスは CHAR(1) のインデックスよりも高速になりますが、事実はありません。これをバックアップします。私の推測では、心配する価値のある大きなパフォーマンスの違いはありません。

ただし、PHP を使用しているため、TINYINT として格納する方がはるかに理にかなっています。1/0 値を使用することは、PHP に文字列として返される場合でもtrueandを使用することと同等であり、そのように処理できます。'y' と 'n' の間で常に変換するのではなく、ブール値のチェックとして結果をfalse単純に実行できます。if ($record['field'])

于 2010-01-07T20:50:53.853 に答える
1
 TINYINT    1 Byte
CHAR(M)     M Bytes, 0 <= M <= 255

違いはありますか?

于 2010-01-07T20:54:10.997 に答える