15

以下は、数百万のレコードを持つデータベースから固定数のレコードを取得するために使用するクエリです。

select * from myTable LIMIT 100 OFFSET 0

私が観察したのは、オフセットがたとえば90000のように非常に高い場合、クエリの実行に時間がかかるということです。以下は、オフセットが異なる2つのクエリ間の時間差です。

select * from myTable LIMIT 100 OFFSET 0       //Execution Time is less than 1sec
select * from myTable LIMIT 100 OFFSET 95000   //Execution Time is almost 15secs

誰かがこのクエリを最適化する方法を教えてもらえますか?つまり、クエリの実行時間は、OFFSETから取得したいレコードの数に関係なく、同じで高速である必要があります。

新しく追加されたもの:-実際のシナリオでは、100万を超えるレコードを持つデータベースがあります。しかし、これは組み込みデバイスであるため、「select * from myTable」を実行してから、クエリからすべてのレコードをフェッチすることはできません。デバイスがクラッシュします。代わりに、上記のクエリに従って、レコードをバッチごとにフェッチし続けます(バッチサイズ= 100または1000レコード)。しかし、私が述べたように、オフセットが増加するにつれて、それは遅くなります。したがって、私の最終的な目的は、データベースからすべてのレコードを読み取りたいということです。ただし、1回の実行ですべてのレコードをフェッチすることはできないため、これを実現するための他の効率的な方法が必要です。

4

5 に答える 5

9

JvdBergが言ったように、インデックスは LIMIT/OFFSET では使用されません。「ORDER BY indexed_field」を追加するだけでは役に立ちません。

ページネーションを高速化するには、LIMIT/OFFSET を避け、代わりに WHERE 句を使用する必要があります。たとえば、主キー フィールドの名前が 'id' でギャップがない場合、上記のコードは次のように書き換えることができます。

SELECT * FROM myTable WHERE id>=0     AND id<100     //very fast!
SELECT * FROM myTable WHERE id>=95000 AND id<95100   //as fast as previous line!
于 2015-05-08T13:02:01.560 に答える
7

95000 のオフセットでクエリを実行すると、以前の 95000 レコードがすべて処理されます。テーブルにインデックスを作成し、それを使用してレコードを選択する必要があります。

于 2012-09-04T14:52:14.163 に答える