3

PostgreSQL 9.1で簡単な実験をしました。test次のようにテーブルを作成しました。

CREATE TABLE test
(
  id serial NOT NULL,
  CONSTRAINT id PRIMARY KEY (id )
)
CREATE INDEX id_idx
  ON test
  USING btree
  (id );

次に、いくつかのデータを追加します。

insert into test values(DEFAULT);
insert into test values(DEFAULT);
insert into test values(DEFAULT);
...many times :)

これtestで、10,000 行のテーブルができました。私の最初の実験は、行を取得することidです:

explain select * from test where id = 50;

Index Scan using id_idx on test  (cost=0.00..8.27 rows=1 width=4)
  Index Cond: (id = 50)

わかりました、ここで奇妙なことは何もありません。値の範囲でクエリを作成しましょう。

explain select * from test where id >= 50;

Seq Scan on test  (cost=0.00..170.00 rows=9951 width=4)
  Filter: (id >= 50)

シーケンシャル スキャンで 9951 行を取得しましたが、最初の 1 行だけを取得したい場合はどうすればよいでしょうか。

explain select * from test where id >= 50 limit 1;

Limit  (cost=0.00..0.02 rows=1 width=4)
  ->  Seq Scan on test  (cost=0.00..170.00 rows=9951 width=4)
        Filter: (id >= 50)

でインデックススキャンが見られると思ってrows=1いましたが、代わりにシーケンシャルスキャンを再度取得しました(スキャン後の制限付き)。SQL クエリでこの動作を実現する方法はありますか?

注:類似の MongoDB クエリがあります。

> db.test.find({'dt':{$gte:ISODate("2013-07-20T00:00:00.00Z")}}).count()
10000
> db.test.find({'dt':{$gte:ISODate("2013-07-20T00:00:00.00Z")}}).limit(1).explain()
{
    "cursor" : "BtreeCursor dt_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 1,
    "nscannedAllPlans" : 1,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 13,
    "indexBounds" : {
        "dt" : [
            [
                ISODate("2013-07-20T00:00:00Z"),
                ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ")
            ]
        ]
    },
    "server" : "******:27017"
}

この場合、MongoDB はインデックス スキャンを使用して 1 つのドキュメントのみをスキャンしましたが、これは素晴らしいことです。

4

1 に答える 1