web-dev-qa-db-ja.com

MySQLおよびPostgreSQLでのクラスター化インデックスのパフォーマンスに関する考慮事項

MySQL/InnoDBでは、クラスター化インデックスは主キーと同義です。したがって、不十分な主キーを選択すると、dbのパフォーマンスに影響します。つまり、PKはデータベース書き込みのパフォーマンスキラーとしてUUIDを使用します。

現在、PostgreSQLには、MySQLのようなクラスター化された制限などはありません。 PKとしてUUIDを選択した場合、どのような影響がありますか? MySQLのようにデータベース書き込みパフォーマンスキラーはPostgreSQLにも存在しますか?

4
Yoga

MySQL

MySQLドキュメンテーション は文字通り_Typically, the clustered index is synonymous with the primary key_と言っていますが、同じものではありません。 クラスター化インデックス(gen_clust_index)と呼ばれます は、PRIMARY KEYのインデックスページとテーブルの行データが同じページに共存するように作成されたことに注意してください。 UUIDなどのPRIMARY KEY値が広いと、BTREEページがはるかに広くなります。データページを分割することもできます。デフォルトの innodb_page_size はMySQLで16KBなので(これは MySQL 5.5でコンパイル済みの固定値であり、back )、16KBページあたりのデータページの行数とPRIMARY KEYナビゲーション用のスペースが少ないことを期待する必要があります。

以前に_PRIMARY KEY_の影響について説明しました。私の投稿を参照してください InnoDB主キーの効率

PostgreSQL

Peter EisentrautからのStackOverflow投稿The maximum length for a value in a B-tree index, which includes primary keys, is one third of the size of a buffer page, by default floor(8192/3) = 2730 bytes.と言っています

PostgreSQL Wiki によれば

テーブルの最大サイズ、行サイズ、および列の最大数は、デフォルトのブロックサイズを32kに増やすことで4倍にできます。テーブルの最大サイズは、テーブルのパーティション分割を使用して増やすこともできます。

このことから、デフォルトの8Kの代わりに32Kブロックを使用するとします。 4倍多くの情報を収めることができますが、それでも何らかの制限があります。

さいわい、UUIDはわずか16バイトです。私はそれから地球を破壊する欠点を期待しません。

分析

InnoDBのクラスタードインデックスの使用は、順序に柔軟性がないため、クラスター化インデックス内のキーを分散するために多くのスペースを管理する必要がないため、小さいキーのメリットがあり、高速書き込みに適しています。

PostgreSQLのストレージエンジンは、MySQLのInnoDBのように制限もテザリングもされていませんが、小さいキーは確実に高速に処理し、より少ないスペースを消費する必要があります。これにより、PostgreSQL、MySQL、またはその他のRDBMSの読み取りおよび書き込みパフォーマンスが向上します。

構造の変更がどのように違いをもたらすかを示すために、MySQLのその他のストレージエンジンMyISAM(非トランザクションであり、クラスター化インデックスを持たない)を使用してみましょう。私はかつてMyISAMテーブルを取り、その行フォーマットを動的から固定長に変更し、他に何も触れずにパフォーマンスが20%向上しました。読み取りパフォーマンスを向上させるために、データを大きくしました。スペース管理をトリガーするメカニズムが少ないため、書き込みパフォーマンスも向上しました(私の投稿 固定サイズフィールドでCHARとVARCHARを使用した場合のパフォーマンスへの影響は何ですか )。

MySQLドキュメンテーション__Optimizing Data Size_ を読むだけで、次のようなフレーズが得られます

小さいテーブルは通常、クエリの実行中にその内容がアクティブに処理されている間、必要なメインメモリが少なくなります。

テーブルデータの領域を削減すると、インデックスが小さくなり、より高速に処理できます。

可能な限り最も効率的な(最小の)データ型を使用します。 MySQLには、ディスク領域とメモリを節約する多くの特殊なタイプがあります。たとえば、小さいテーブルを取得するには、可能であれば小さい整数型を使用します。 MEDIUMINT列は25%少ないスペースを使用するため、MEDIUMINTは多くの場合INTよりも優れた選択です。

より小さなデータ型についての私のポイントをさらに進めるために、MySQLの SELECT ... PROCEDURE ANALYSE(); について言及します。 SELECT * FROM tablename PROCEDURE ANALYSE();を実行すると、出力はデータ、最小値、最大値、平均値、値のSTD、および各列の推奨データ型(ここでの主なポイント)の分析です。

_ALTER TABLE_コマンドを適用して推奨されるデータ型を適用する場合、テーブルは最終的に小さくなる必要があります。

PostgreSQLでさえ、より小さなデータ型の恩恵を受ける必要があります。どうやって ?

PostgreSQLには TOAST(Outside Attribute Storage Technique) と呼ばれるこのメカニズムがあることを思い出してください(以前の記事を参照してください(私の投稿を参照してください 提案:MySQL blob処理リビジョン がある場合は行データをジャグリングする必要があります)明らかに、このメカニズムはトリガーされません。すべての行が小さく、多くの行がPostgreSQLの8Kブロックに快適に収まるからです。

結論

あなたの質問はPostgreSQLに焦点を当てているようですので、このような質問に答えさせてください。

PKとしてUUIDを選択した場合、どのような影響がありますか? MySQLのようにデータベース書き込みパフォーマンスキラーはPostgreSQLにも存在しますか?

PostgreSQLは、列の値が小さいほど書き込み処理が速くなります。 UUIDは16バイトです。 8バイト整数をPRIMARY KEYとして使用すると、UUIDよりも書き込みと処理が高速になります。 4バイト整数はそれよりもさらに高速です。このすべてからの教訓?必要がなければ、_PRIMARY KEY_の値を大きくして速度を落とさないでください。

2
RolandoMySQLDBA

UUIDがシーケンシャルバリアントではない場合、作成された順序でUUIDを挿入すると、挿入された行ごとにインデックス内のランダムなリーフノードが汚染されます。インデックスが十分な大きさになると、ディスクへの効率的な書き込みのために書き込みを統合できないため、回転しているハードドライブの書き込みパフォーマンスが低下します。

1
jjanes

MySQLから離れて実行していて、PostgreSQLがより優れていることを期待している場合は、最初に、使用しているUUIDのタイプを検討してください。それらが「順次バリアント」(タイプ1)であり、時間によるクラスタリングがある場合、MySQL(または任意のデータベース)はそれを利用できます。以下はそのようなものの議論です: http://mysql.rjweb.org/doc.php/uuid

MySQLにはUUIDのデータ型はありませんが、CHAR(36)とBINARY(16)の間の変換は非常に簡単です。上記のリンクはそれも示しています。

0
Rick James