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 つのドキュメントのみをスキャンしましたが、これは素晴らしいことです。