web-dev-qa-db-ja.com

INTではなくTINYINTを使用する場合

一般に、私は常にIntsを使用します。ただし、理論的にはこれがベストプラクティスではないことはわかっています。これは、データの保存が保証されている最小のデータ型を使用する必要があるためです。

たとえば、保存するデータが1、0、またはnullであることがわかっている場合は、tinyintを使用することをお勧めします(2または3に拡張する可能性は非常に低いです)。

ただし、これを行う理由として私が知っている唯一の理由は、ストレージの目的です。つまり、4バイトではなく1バイトを1行に使用します。

tinyint(またはsmallintまたはbigint)をintだけで使用すると、ハードドライブの容量を節約する以外にどのような影響がありますか?

92
Richard

ディスク容量は安いです...それはポイントではありません!

ストレージスペースの観点から考えるのではなく、代わりにバッファープールと ストレージ帯域幅 について考えます。極端に言えば、CPUキャッシュと メモリバス帯域幅 です。リンクされた記事はシリーズの一部であり、クラスター化されたキーの選択に問題があることを強調しています(INT vs GUID vs Sequential GUID))が、バイトの違いを強調しています。

最も重要なメッセージはデザインの問題です。 VLDBテリトリーに到達するまで、適切に指定されたサーバー上の個々のデータベースには違いが表示されませんが、数バイトを節約できる場合は、そうしないでください。

以前の質問 で説明されている環境を思い出します。 SQLインスタンスごとに、サイズが50 MB〜50 GBの400以上のデータベース。その環境全体で、レコードごと、テーブルごと、データベースごとに数バイトをスクラブすると、大きな違いが生じる可能性があります。

92

他の回答に加えて...

行とインデックスエントリは8kページに格納されます。したがって、1行あたり3バイトの100万行は、ディスク上で3 MBではありません。ページあたりの行数(「ページ密度」)に影響します。

Nvarcharからvarchar、smalldatetimeからdatetime、intからtinyintなどにも同じことが当てはまります。

編集、2013年6月

http://sqlblog.com/blogs/joe_chang/archive/2013/06/16/load-test-manifesto.aspx

この記事では

重要な基準は、カーディナリティーとページ対行の比率です。

したがって、データ型の選択は重要です

29
gbn

考慮すべきは、テーブルストレージだけではありません。 int列が複合キーの一部であるインデックスを使用する場合、当然、インデックスページをできるだけいっぱいにする必要があります。これは、インデックスエントリができるだけ小さいためです。

BTREEページのインデックスエントリを調べると、データタイプが小さい場合は少し速くなることが確実にわかるでしょう。ただし、インデックスエントリに含まれるVARCHARは、INTよりもTINYINTを使用することによるパフォーマンスの向上を相殺(無効化)します。

それにもかかわらず、インデックスエントリに複合エントリがあり、すべてが整数である場合、整数が小さいほどバイト数が多く、高速で高速です。

14
RolandoMySQLDBA

データベースが大きくなると、すべてが複雑になります。

  • メンテナンスウィンドウを拡大または再スケジュールする必要がある
  • バックアップ(1日の終わりの完全バックアップはばかげて時間を浪費するため、差分バックアップまたはログバックアップが必要であり、週に1回、おそらく月に1回)完全バックアップを実行します)
  • パフォーマンスのメンテナンスは時間を浪費するようになり(数百万行のテーブルにインデックスを作成するには、実行するのにそれほど時間はかかりません)、スケジュールを変更する必要があり、テーブルが広い場合は悪化します...
  • そして、ネットワーク経由で100Gbのバックアップを送信することは、私が簡単に言うことではありません-特に(不明な理由で)ネットワークが75Gbマークに接続をドロップすることに頑固である場合...(私が働いていたインストールで、ネットワーク上のマップされたドライブにバックアップしていました-ネットワーク)...

そして、それとどのようなデータ型が関係しているのでしょうか? EVERYTHING。必要以上に大きい行サイズを使用すると、必要以上にデータベースページがいっぱいになり、行サイズがこのような場合はスペースが無駄になるページに記録できるレコードは1つだけです。その結果、書き込みと読み取りに必要なページが増え、キャッシュに多くのRAMメモリが使用されます(大きなレコードには大きなメモリが必要です)。そして、データ型がディスクから必要とされるよりも大きく指定されているため、インデックス同じ問題が発生します-特に、その複合2 BIGINT列の主キーをクラスター化する場合、作成された他のインデックスはその主キーを暗黙的にそれらの定義にコピーするためです。

数百万の行があるテーブルの一部の列、またはデータを格納するために4バイトの整数を必要としないが数百万行にFKされる小さなテーブルでさえ、2バイトであることがわかっている場合十分-[〜#〜] smallint [〜#〜]を使用します。 0〜255の範囲の値で十分な場合は、[〜#〜] tinyint [〜#〜]です。はい/いいえフラグ? [〜#〜] bit [〜#〜]があります。

13
Fabricio Araujo

tinyintintの場合、ディスク領域、ページ分割、メンテナンス時間などの明確な違いがありますが、varcharの場合、これらはありません。

それでは、すべてのテキストフィールドをvarchar(4000)として宣言しないでください。とにかく、必要なスペースだけを使い果たすからです。さらに、データが決して切り捨てられないことが保証されます。

答えはもちろんです:

  1. 意図の明確化(名前フィールドを4000文字にする必要がある理由を誰も理解できないため)
  2. 伝記全体を名前として入力しないようにするための検証。

これらのまったく同じ理由がtinyintにも当てはまります。

9
yoel halb