6

次の文字列に一致する、データベースに最後に入力されたレコード (最大 ID)を検索するとしますModel.where(:name => 'Joe')。100,000 件以上のレコードがあります。多くの一致があります (たとえば、数千)。

これを行う最も効率的な方法は何ですか? PostgreSQL はすべてのレコードを見つける必要がありますか、それとも最後のレコードだけを見つけることができますか? これは特に遅いクエリですか?

Rails 3.0.7、Ruby 1.9.2、および PostgreSQL 8.3 で作業しています。

4

3 に答える 3

8

ここで重要な部分は、一致する indexを持つことです。この小さなテスト セットアップを試すことができます。

xテスト用のスキーマを作成します。

-- DROP SCHEMA x CASCADE;  -- to wipe it all for a retest or when done.
CREATE SCHEMA x;
CREATE TABLE x.tbl(id serial, name text);

10000 のランダムな行を挿入します。

INSERT INTO x.tbl(name) SELECT 'x' || generate_series(1,10000);

名前が繰り返される別の 10000 行を挿入します。

INSERT INTO x.tbl(name) SELECT 'y' || generate_series(1,10000)%20;

ランダムな 10% を削除して、よりリアルにします。

DELETE FROM x.tbl WHERE random() < 0.1;

ANALYZE x.tbl;

クエリは次のようになります。

SELECT *
FROM   x.tbl
WHERE  name = 'y17'
ORDER  BY id DESC
LIMIT  1;

--> 総実行時間: 5.535 ミリ秒

CREATE INDEX tbl_name_idx on x.tbl(name);

--> 総実行時間: 1.228 ミリ秒

DROP INDEX x.tbl_name_idx;
CREATE INDEX tbl_name_id_idx on x.tbl(name, id);

--> 総実行時間: 0.053 ミリ秒

DROP INDEX x.tbl_name_id_idx;
CREATE INDEX tbl_name_id_idx on x.tbl(name, id DESC);

--> 総実行時間: 0.048 ミリ秒

DROP INDEX x.tbl_name_id_idx;
CREATE INDEX tbl_name_idx on x.tbl(name);
CLUSTER x.tbl using tbl_name_idx;

--> 総実行時間: 1.144 ミリ秒

DROP INDEX x.tbl_name_id_idx;
CREATE INDEX tbl_name_id_idx on x.tbl(name, id DESC);
CLUSTER x.tbl using tbl_name_id_idx;

--> 総実行時間: 0.047 ミリ秒

結論

フィッティング インデックスを使用すると、クエリの実行速度が 100 倍以上速くなります。
トップ パフォーマーは、最初にフィルター列があり、最後に並べ替え列がある複数列インデックスです。この場合、インデックスの並べ替え順序を
一致させると少し役立ちます。

クラスタリングは単純なインデックスに役立ちます。これは、まだ多くの列をテーブルから読み取る必要があり、クラスタリング後に隣接するブロックでこれらの列を見つけることができるためです。この場合、テーブルからフェッチする必要があるレコードは 1 つだけなので、複数列のインデックスには役立ちません。マルチカラム インデックスの
詳細については、マニュアルを参照してください。

これらの効果はすべて、テーブルのサイズとともに大きくなります。2 つの小さな列の 10000 行は、非常に小さなテスト ケースです。

于 2011-11-21T19:47:23.653 に答える
6

Rails でクエリをまとめると、ORM が適切な SQL を記述します。

Model.where(:name=>"Joe").order('created_at DESC').first

これにより、すべてのモデル レコードが取得されたり、テーブル スキャンが行われたりすることはありません。

于 2011-11-21T18:42:34.260 に答える
-1

これはおそらく最も簡単です:

SELECT [columns] FROM [table] WHERE [criteria] ORDER BY [id column] DESC LIMIT 1

注: ここでは、索引付けが重要です。巨大な DB は、正しい方法でインデックスを作成していないと、どのように検索しても遅くなります。

于 2011-11-21T18:10:57.630 に答える