2017-02-16 8 views
2

Peopleテーブル(Id, first_name, last_name)があります。プライマリキーはidです。私は(last_name, first_name, Id)で注文されたテーブルの最初のN人を調べることができるようにしたい。場合によっては、次のN人などを検索する必要があります。私はこれを効率的にやりたいこれを行う最善の方法は何ですか?ページネーションを実装するにはどうすればよいですか?

答えて

3

は、主に次の2つの方法があります。

  • 使用LIMITOFFSET
  • 使用LIMITとキーの-前のページ

OFFSET戦略は、あなたが任意のページを読むことができますが、クエリが実行されるたびに前のすべてのページから行を読み込む必要があるため、効率的ではありません。実装するのが最も簡単で、受け入れ可能な戦略です(特に最初の数ページだけが必要な場合)。しかし、一般的には推奨されません。前のページの主要な戦略では、ページは順番に読み込まれる必要がありますが、各ページは必要な行だけを読み込むため、より効率的です。

それでは、(LastName, FirstName, Id)順あなたのテーブルから結果をフェッチするために元のクエリから始めましょう:

SELECT 
    t.id, 
    t.first_name, 
    t.last_name 
FROM 
    People as t 
ORDER BY 
    t.last_name, 
    t.first_name, 
    t.id 
LIMIT 
    @limit_rows 

あなたはおそらく、「クエリのすべては、データベースのデータの一貫性のあるスナップショットを表示することを確実にしたいので、あなたでしょうクエリのシーケンスが常に同じタイムスタンプから読み取られるようにします。これを達成する最も簡単な方法は、最初のクエリがreturnReadTimestampがtrueに設定されたReadOnlyトランザクションであることです。その後、後続のクエリはReadOnlyトランザクションでもあり、元のクエリによって返された同じタイムスタンプをreadTimestampとして使用する必要があります。どのような方法を選択しても、ORDER BY句は、一連の問合せ全体で一貫した結果を保証するために不可欠です。 返される最後の行が(1709, "John", "Smith")であるとします。そして、結果の次のページを取得するクエリで、あなたの最初の試みは、次のようになります。

SELECT 
    t.id, 
    t.first_name, 
    t.last_name 
FROM 
    People as t 
WHERE 
    t.last_name > "Smith" 
    OR 
    (t.last_name = "Smith" and t.first_name > "John") 
    OR 
    (t.last_name = "Smith" and t.first_name = "John" AND t.id > 1709) 
ORDER BY 
    t.last_name, 
    t.first_name, 
    t.id 
LIMIT 
    @limit_rows 

真ん中WHERE句が新しく追加されました。しかし、この述語を書くことは、あなたが考えるかもしれないよりも厄介です。 NULL値を処理する必要があります。あなたは、異なるid値を持つJohn Smithという名前の複数の人がいる場合を処理する必要があります。浮動小数点数とNaNの値には本当に注意が必要です。 Cloud SpannerのRead APIは、テーブルの範囲スキャンのページ付けを容易にするため、このような場合にも役立ちます。

+0

こんにちはマイク、これを投稿していただきありがとうございます。スナップショットを使用してタイムスタンプを提供している場合は、それらのすべての制約を追加する必要があります。あなたはちょうどt.id> 1709と言うことができませんでしたか?または、ガベージコレクションのためにスナップショットが期限切れになったケースをカバーしようとしていますか? – Bradford

+0

ガベージコレクションはここでは無関係です。余分な制約の理由は、問合せの結果を主キー順序と同じではない(姓、名、ID)の順番で戻したいという質問があるためです。 t.idが1709未満であり、これがまだ必要な結​​果である結果がある可能性があることに注意してください(例:「Wilkes」、「Bob」、805) –

0

MySQLとPostgreSQLの両方とも、LIMIT句で通常使用されるOFFSETという非常に便利な機能をサポートしています。

LIMIT句は、SQL文で返される結果の数を制限するために使用されます。

SELECT column FROM table LIMIT 10 

これは、Microsoft SQL Server上TOP句に似ています:あなたがテーブル内の1000行を持っていますが、最初の10を返すようにしたいのであれば、あなたはこのような何かをするだろう。しかし、LIMIT句は、MySQLとPostgreSQLのクエリの最後にあります。

ここで、結果11-20を表示するとします。キーワードOFFSETその同じくらい簡単に、次のクエリを実行します:

SELECT column FROM table LIMIT 10 OFFSET 10 

をこれにより、簡単にSQLを使用したマルチページの結果や改ページをコーディングすることができます。多くの場合、すべてのレコードを選択してから、データベースに直接アクセスするのではなく、アプリケーション・サーバー層でフィルタリングします。データベース上でこれを実行すると、パフォーマンスが大幅に向上することが想像されます。

関連する問題