MY PLATFORM:
PHPとmySQL
私の状況:
テーブルの列の1つにユーザー選択の値を格納する必要がある状況に遭遇しました。今私のオプションは次のようになります:
私の質問:
だから私は、上記の2つのタイプのどちらかを知りたいと思いました:
その列にアクセスするときのクエリ速度が速くなります(簡単にするために、他のクエリを混在させたり、他の列にアクセスしたりしないでください)。
データを保存してアクセスする最も効率的な方法とその理由は何ですか?
列にインデックスが付けられている場合とされていない場合、アクセス速度はどのように異なりますか?
私の理解では、char(1)とtinyint(1)は1バイトのスペースしか使用しないため、この場合、ストレージスペースは問題になりません。次に残るのはアクセス速度です。私の知る限り、数値インデックスは他の何よりも高速で効率的です。しかし、ここでのケースは決定するのが難しいと思います。これについてのあなたの経験を絶対に聞きたいです。
前もって感謝します。
ENUM('n','y')
で列を作成する必要があると思います。 Mysqlはこのタイプを最適な方法で保存します。また、許可された値のみをフィールドに保存するのにも役立ちます。
また、パフォーマンスに影響を与えることなく、より人間に優しいENUM('no','yes')
にすることもできます。文字列'no'
および'yes'
は、ENUM
定義ごとに1回だけ保存されます。 Mysqlは、行ごとの値のインデックスのみを格納します。
ENUM
列による並べ替えについても注意してください。
ENUM値は、列挙型メンバーが列仕様にリストされている順序に従ってソートされます。 (つまり、ENUM値はインデックス番号に従ってソートされます。)たとえば、ENUM( 'a'、 'b')の場合は 'a'は 'b'の前にソートされますが、ENUMの場合は 'b'は 'a'の前にソートされます。 ( 'b'、 'a')。
_ 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
のようです。コードは ここにあります
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と見なされます。ゼロ以外の値は真と見なされます。
MySQLがTINYINT(1)をBOOLEANと同一視するところまで進んだ場合、それは進むべき道のようです。
確実に知るには、ベンチマークを行う必要があります。または、プロジェクト全体の壮大な視点では、おそらくそれほど重要ではないことを知ってください。
Char列にはエンコーディングと照合順序があり、それらを比較するとエンコーディング間の不要な切り替えが発生する可能性があるため、intの方が高速になると思います。同じ理由で、int列のインデックスの更新も高速だと思います。しかし、繰り返しになりますが、それはそれほど重要ではありません。
CHAR
は、選択した文字セットとテーブルオプションによっては、複数のバイトを使用する場合があります。一部の文字はエンコードに3バイトかかることがあるため、y
とn
のみを使用している場合でも、MySQLはそのスペースを予約することがあります。
それらは両方とも非常に接近しているので、それは問題ではありません。 SOでこの質問をしなければならないと感じた場合は、最適化しすぎています。最も論理的に意味のある方を使用してください。
MySQLでテーブルを作成するときに、タイプBOOL
またはBOOLEAN
を列タイプとして指定すると、列タイプはTINYINT(1)
として作成されます。おそらくこれは2つのうち速い方です。
また:
将来のMySQLリリースでは、標準SQLに従って完全なブール型処理を実装する予定です。
文字列処理のオーバーヘッド(照合、空白など)がないため、TINYINTのインデックスはCHAR(1)のインデックスよりも高速であるというのが私の予感ですが、私には何の事実もありません。これをバックアップします。私の推測では、心配する価値のある大きなパフォーマンスの違いはありません。
ただし、PHPを使用しているため、TINYINTとして保存する方がはるかに理にかなっています。 1/0値を使用することは、文字列としてPHPに返される場合でも、true
およびfalse
を使用することと同等であり、そのように処理できます。常に「y」と「n」の間で変換する代わりに、結果をブールチェックとしてif ($record['field'])
を実行するだけで済みます。
TINYINT 1 Byte
CHAR(M) M Bytes, 0 <= M <= 255
何か違いはありますか?