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

LIMIT1のインデックス付きORDERBY

    大きなテーブルを扱っていると仮定します 、部分インデックス 役立つかもしれません:

    CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC)
    WHERE created_at > '2013-09-15 0:0'::timestamp;
    

    すでにお気づきのとおり、ここでは降順または昇順はほとんど問題になりません。 Postgresはほぼ同じ速度で逆方向にスキャンできます(例外は複数列のインデックスに適用されます)。

    このインデックスを使用するためのクエリ:

    SELECT * FROM tbl
    WHERE  created_at > '2013-09-15 0:0'::timestamp -- matches index
    ORDER  BY created_at DESC
    LIMIT  1;
    

    ここでのポイントは、インデックスをはるかに小さくすることです。 、したがって、キャッシュと保守が簡単になるはずです。

    1. 最新のタイムスタンプよりも小さいことが保証されているタイムスタンプを選択する必要があります。
    2. 古いデータを切り取るために、時々インデックスを再作成する必要があります。
    3. 条件はIMMUTABLEである必要があります 。

    したがって、1回限りの効果は時間の経過とともに低下します。 特定の問題 ハードコードされた条件です:

    WHERE created_at > '2013-09-15 0:0'::timestamp
    

    自動化

    インデックスとクエリは時々手動で更新できます。または、次のような関数を使用して自動化します。

    CREATE OR REPLACE FUNCTION f_min_ts()
      RETURNS timestamp LANGUAGE sql IMMUTABLE AS
    $$SELECT '2013-09-15 0:0'::timestamp$$
    

    インデックス:

    CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC);
    WHERE created_at > f_min_ts();
    

    クエリ:

    SELECT * FROM tbl
    WHERE  created_at > f_min_ts()
    ORDER  BY created_at DESC
    LIMIT  1;
    

    cronジョブまたはトリガーベースのイベントを使用してレクリエーションを自動化します。クエリは同じままになります。ただし、すべてのインデックスを再作成する必要があります この関数を変更した後、何らかの方法でこの関数を使用します。それぞれをドロップして作成するだけです。

    最初..

    ...これで実際にボトルの首に当たっているかどうかをテストします。

    単純なDROP index ... ; CREATE index ... 仕事をします。次に、インデックスが肥大化した可能性があります。自動真空設定がオフになっている可能性があります。

    または、VACUUM FULL ANALYZEをお試しください テーブル全体とインデックスを元の状態に保ち、もう一度確認します。

    その他のオプション テーブルから実際に取得するものに応じて、通常の一般的なパフォーマンスチューニングとカバーインデックスを含めます。




    1. 文字列値1、2をOracleクエリへの入力として渡すことができません

    2. PostgreSQLでユーザーをスーパーユーザーに変更する方法

    3. DjangoORMでPostgreSQL配列フィールドをマッピングする方法

    4. PHPで安全なmysqlプリペアドステートメントを作成するにはどうすればよいですか?