REINDEXは危険ですか?


17

COUNT(*)主キーを持つ150,000行のテーブルを試しました。約5分間のツールなので、これはインデックス作成の問題であることがわかりました。

PostgreSQLマニュアルの引用:

REINDEXは、インデックスの内容を最初から再構築するという点で、インデックスのドロップと再作成に似ています。ただし、ロックに関する考慮事項はかなり異なります。REINDEXは、インデックスの親テーブルの書き込みをロックしますが、読み取りはロックしません。また、処理中の特定のインデックスの排他ロックを取得し、そのインデックスを使用しようとする読み取りをブロックします(...)後続のCREATE INDEXは書き込みをロックしますが、読み取りはロックしません。インデックスが存在しないため、読み取りはインデックスを使用しようとしません。つまり、ブロッキングは発生しませんが、読み取りは高価な順次スキャンに追い込まれる可能性があります。

あなた自身の経験から、あなたは言うことができます:

  • あるREINDEXING危険な?データの一貫性を損なうことはありますか?
  • 時間がかかりますか?
  • それは私のシナリオのおそらく解決策ですか?

更新:

私たちのために働いた解決策は、別の名前で同じインデックスを再作成し、古いインデックスを削除することでした。

インデックスの作成は非常に高速であり、インデックスサイズを650 MBから8 MBに削減しました。COUNT(*)withの使用にはbetween3秒しかかかりません。

回答:


15

インデックスの再作成は危険ではなく、データの一貫性を損なうことはありません。ただし、タイムクリティカルな書き込みがある場合、テーブルがロックされ、DMLが中止されると、データが失われる可能性があります。

インデックスの再作成にはそれほど時間はかかりませんが、通常はテーブル全体の読み取り、インデックスフィールドの並べ替え、新しいインデックスの書き込みが必要になります。時間COUNT(*)がかかる場合は、おそらく5分以上かかります。

これがインデックス作成の問題である可能性は低いです。 COUNT(*)テーブルスキャンを使用する必要があります。この場合、インデックスは読み込まれません。何らかのIO問題が発生すると予想されます。

を使用するCOUNT(1)COUNT(pk_field)、インデックスを使用する可能性があります。

UnixまたはLinuxプラットフォームで実行している場合は、でディスクアクティビティを監視できますsar。また、IOレートを大幅に削減できる障害のあるディスクがある場合もあります。

ラージオブジェクトを含むテーブルでは、IOを大幅に増やして、COUNT(*)のレコードを構築することもできます。


2
wiki.postgresql.orgによるCOUNT(*)と、最良の選択ですIf you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
。– orange80

1

私はあなたのための最良の答えがわからない。ただし、このスレッドはいくつかの良い提案を提供しているようです:n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

1つの注意点は、TRIGGERを実装して、行カウントを別のテーブルに保持できることです(COUNT(*)がアプリケーションによって頻繁に呼び出される場合)。

応答のいくつかは、これが最近十分にバキュームされていないデータベースの兆候であることを示唆しています(サーバーまたは特にそのデータベースで自動バキュームが無効になっていることを示唆しています)?

別の提案は次のようになります。

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

そして、A。Kretschmerと特定された誰かは次のように述べています。

いいえ。現在のインデックス実装には、現在のトランザクション内の行の可視性に関する情報は含まれていません。現在のトランザクション内で現在の行が表示されるかどうかを取得するには、データテーブル全体をスキャンする必要があります。

...行レベルのアクセス許可がパフォーマンスの問題であるという私のコメントをサポートしています。

私の検索でも、WikiVS:MySQL vs. PostgreSQL:COUNT(*)が見つかりました

Google:postgresql count(*)performanceを使用して、私が見つけた他の結果を熟読できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.