sql >> データベース >  >> RDS >> PostgreSQL

Postgresタイムスタンプクエリ範囲を最適化する

    CLUSTER

    CLUSTERを使用する場合 、表示された構文は無効です。

    create CLUSTER ticket USING ticket_1_idx;

    1回実行:

    CLUSTER ticket USING ticket_1_idx;
    

    これはできます より大きな結果セットで大いに役立ちます。返される単一の行についてはそれほど多くはありません。
    Postgresは、後続の呼び出しに使用するインデックスを記憶しています。テーブルが読み取り専用でない場合、効果は時間の経過とともに低下し、特定の間隔で再実行する必要があります:

    CLUSTER ticket;
    

    おそらく揮発性パーティションでのみ。以下を参照してください。

    ただし 、更新が多い場合は、CLUSTER (またはVACUUM FULL )実際にはパフォーマンスが悪い可能性があります。適切な量​​の膨張により、UPDATEが可能になります 同じデータページに新しい行バージョンを配置し、OSで基になるファイルを頻繁に物理的に拡張する必要をなくします。慎重に調整されたFILLFACTORを使用できます 両方の世界を最大限に活用するには:

    • PKであるシーケンシャルインデックスのフィルファクター

    pg_repack

    CLUSTER テーブルの排他ロックを取得します。これは、マルチユーザー環境で問題になる可能性があります。マニュアルの引用:

    テーブルがクラスター化されている場合、ACCESS EXCLUSIVE ロックが取得されます。これにより、他のデータベース操作(読み取りと書き込みの両方)が防止されます。 )テーブルでの操作からCLUSTERまで 終了しました。

    大胆な強調鉱山。代替のpg_repackを検討してください :

    CLUSTERとは異なり およびVACUUM FULL 処理中に処理されたテーブルを排他的にロックすることなく、オンラインで動作します。 pg_repackは起動に効率的で、CLUSTERを使用した場合と同等のパフォーマンスを発揮します。 直接。

    および:

    pg_repackは、再編成の最後に排他ロックを取得する必要があります。

    バージョン1.3.1は以下で動作します:

    PostgreSQL 8.3、8.4、9.0、9.1、9.2、9.3、9.4

    バージョン1.4.2は以下で動作します:

    PostgreSQL 9.1、9.2、9.3、9.4、9.5、9.6、10

    クエリ

    クエリは、それ自体がパフォーマンスの問題を引き起こさないほど単純です。

    ただし、正しさに関する一言 :BETWEEN コンストラクトincludes 国境。クエリで12月19日、 plus のすべてが選択されます 12月20日00:00時間からの記録。それは非常にありそうもない 要件。たぶん、あなたは本当に欲しいです:

    SELECT *
    FROM   ticket 
    WHERE  created >= '2012-12-19 0:0'
    AND    created <  '2012-12-20 0:0';
    

    パフォーマンス

    まず、あなたは尋ねます:

    シーケンシャルスキャンを選択するのはなぜですか?

    あなたのEXPLAIN 出力には、インデックススキャンが明確に示されています 、シーケンシャルテーブルスキャンではありません。ある種の誤解があるに違いありません。

    パフォーマンスを向上させるために強く迫られている場合は、状況を改善できる可能性があります。しかし、必要な背景情報は問題ではありません。可能なオプションは次のとおりです。

    • *ではなく、必要な列のみをクエリできます 転送コスト(および場合によっては他のパフォーマンス上の利点)を削減するため。

    • パーティショニングを見ることができます 実用的なタイムスライスを別々のテーブルに配置します。必要に応じて、パーティションにインデックスを追加します。

    • パーティショニングがオプションではない場合、関連するがそれほど煩わしくない別の手法は、1つ以上の部分インデックスを追加することです。 。
      たとえば、主に今月をクエリする場合 、次の部分インデックスを作成できます:

      CREATE INDEX ticket_created_idx ON ticket(created)
      WHERE created >= '2012-12-01 00:00:00'::timestamp;
      

      CREATE 直前の新しいインデックス 新しい月の始まり。 cronジョブを使用してタスクを簡単に自動化できます。オプションでDROP 数か月後の部分インデックス。

    • CLUSTERの合計インデックスに加えて保持します (部分インデックスでは動作できません)。古いレコードが変更されない場合は、新しいパーティションを再クラスター化するだけでよいため、テーブルのパーティション化はこのタスクに大いに役立ちます。レコードがまったく変更されない場合は、おそらくCLUSTERは必要ありません。 。

    最後の2つのステップを組み合わせると、パフォーマンスは素晴らしいはずです。

    パフォーマンスの基本

    基本の1つが欠けている可能性があります。通常のパフォーマンスに関するアドバイスがすべて適用されます:

    • https://wiki.postgresql.org/wiki/Slow_Query_Questions
    • https://wiki.postgresql.org/wiki/Performance_Optimization



    1. レコードが見つからない場合はゼロを返します

    2. SQLServerANSI_NULLSの説明

    3. cPanelでMySQLデータベースを作成する方法

    4. UnixtimeをDatetimeSQLに変換する(Oracle)