その制限条項なしで何行があったでしょうか?


あなたはOopsからモジュラーの概念に精通している、右?それで、私の導入はこのポストにありません.😆


内容

  • Introduction

  • Explanation
  • MySQL
  • Postgres
  • Conclusion
  • References
  • Further Reads
  • 導入


    のは、イベント管理会社のためのこのソフトウェアを構築していると言う、すべてのイベントのデジタルを追跡する.それで、あなたはフロントエンドdevをUIで準備しておきます、そして、彼女があなたから必要とするすべては2つのものです.
  • 今年既に起こった出来事のリスト(ページごとに10行ずつ)
  • 同じ総数
  • あることを考えるevents あなたのSQLデータベースのテーブルでは、単にコーディングを取得し、彼女の要件を満たすために2つの別々のエンドポイントを提供することができます.
    SELECT id, organiser_id, venue_id, scheduled_date
    FROM events
    WHERE scheduled_date < NOW()
    LIMIT 10 OFFSET 0;
    
    上記の質問は、あなたがユーザーが一度にGUI上で見たがっている多くの記録に従って限界とオフセットを提供することを与えられると、与えられたページ化された方法で望ましい詳細を得る際に、タスク1の要件を提供します.
    SELECT COUNT(*) AS total
    FROM events
    WHERE scheduled_date < NOW();
    
    そして、このクエリは、指定された条件に一致するレコードの総数を取得します.
    これは彼女の要件を十分にするだろうし、また、どのように迅速にこれを実装することができます彼女に感銘を与えるでしょう.

    解説


    以下の質問を書きましょう.
    SELECT id, organiser_id, venue_id, scheduled_date
    FROM events
    WHERE scheduled_date < NOW()
    LIMIT 10 OFFSET 0;
    
    +------+--------------+----------+----------------+
    | id   | organiser_id | venue_id | scheduled_date |
    +------+--------------+----------+----------------+
    |    4 |            6 |        2 | 2021-02-20     |
    |    5 |            4 |        6 | 2021-05-29     |
    |    6 |            4 |        7 | 2021-02-14     |
    |    7 |            1 |        2 | 2021-06-23     |
    |    8 |            2 |       10 | 2021-06-30     |
    |   10 |            1 |       13 | 2021-08-01     |
    |   11 |            5 |        6 | 2021-02-28     |
    |   12 |            4 |        4 | 2021-07-07     |
    |   19 |            3 |        5 | 2021-07-21     |
    |   26 |            4 |        1 | 2021-02-12     |
    +------+--------------+----------+----------------+
    10 rows in set (0.01 sec)
    
    SELECT COUNT(*) AS total
    FROM events
    WHERE scheduled_date < NOW();
    
    +-------+
    | total |
    +-------+
    |    54 |
    +-------+
    1 row in set (0.01 sec)
    
    最初のクエリで起こるのは、SQL ServerがWHERE つの大きなSupersetのような条項は、あなたにそれについて言及しますLIMIT 条項.これは完全に罰金です.
    しかし、2番目のクエリを実行するときには、サーバーにとってそんなにうまくいかないところがあります.それは再び、最初のクエリで行われたのと同じ手順を実行し、スーパーセットを作成し、それをカウントします.
    だから、それはあなたの全体のクエリを評価するだけであなたを得るために同じことを行いますか?それは過ちではないか.

    さて、SQL Serverを負担することなく、他の方法を達成する方法は?
    それで、いくつかのSQL解決はあなたにこの方法を提供します.MySQLとPostgresの効率的な方法でどうやってこれを行うかを教えてください.

    MySQL

    SQL_CALC_FOUND_ROWS クエリ修飾子か、単にそのようなキーワードを言いますDISTINCT を使用してSELECT 文.
    SELECT SQL_CALC_FOUND_ROWS id, organiser_id, venue_id, scheduled_date
    FROM events
    WHERE scheduled_date < NOW()
    LIMIT 10 OFFSET 0;
    
    +------+--------------+----------+----------------+
    | id   | organiser_id | venue_id | scheduled_date |
    +------+--------------+----------+----------------+
    |    4 |            6 |        2 | 2021-02-20     |
    |    5 |            4 |        6 | 2021-05-29     |
    |    6 |            4 |        7 | 2021-02-14     |
    |    7 |            1 |        2 | 2021-06-23     |
    |    8 |            2 |       10 | 2021-06-30     |
    |   10 |            1 |       13 | 2021-08-01     |
    |   11 |            5 |        6 | 2021-02-28     |
    |   12 |            4 |        4 | 2021-07-07     |
    |   19 |            3 |        5 | 2021-07-21     |
    |   26 |            4 |        1 | 2021-02-12     |
    +------+--------------+----------+----------------+
    10 rows in set, 1 warning (0.01 sec)
    
    結果は同じに見えます.しかし、ここで起こることは、supersetを作って、あなたを返すことの間ですLIMIT EDレコードは、SQLエンジンはすべてカウントされ、メモリ内の任意の場所を格納します.さて、どのように1つのアクセスになりますか?
    SELECT FOUND_ROWS() AS total;
    
    +-------+
    | total |
    +-------+
    |    54 |
    +-------+
    1 row in set, 1 warning (0.00 sec)
    
    使用したクエリの直後に上記のクエリを実行するSQL_CALC_FOUND_ROWS クエリ修飾子は、以前のクエリの処理中に格納されたカウントを返します.したがって、LIMIT 条項.😄
    Although MySQL deprecated this feature パフォーマンスの問題のため、彼らは実際にそれを削除するまで、まだそれを使用することができます.

    Postgres


    この特定のケースのために、初期の質問は変わりません.
    SELECT id, organiser_id, venue_id, scheduled_date
    FROM events
    WHERE scheduled_date < NOW()
    LIMIT 10 OFFSET 0;
    
     id | organiser_id | venue_id | scheduled_date
    ----+--------------+----------+----------------
      4 |            6 |        2 | 2021-02-20
      5 |            4 |        6 | 2021-05-29
      6 |            4 |        7 | 2021-02-14
      7 |            1 |        2 | 2021-06-23
      8 |            2 |       10 | 2021-06-30
     10 |            1 |       13 | 2021-08-01
     11 |            5 |        6 | 2021-02-28
     12 |            4 |        4 | 2021-07-07
     19 |            3 |        5 | 2021-07-21
     26 |            4 |        1 | 2021-02-12
    (10 rows)
    
    SELECT COUNT(*) AS total
    FROM events
    WHERE scheduled_date < NOW();
    
     total
    ------------
        54
    (1 row)
    
    同様のことがここでも起こります.The WHERE 節を2回評価する必要があります.
    しかし、Postgresはこのコンセプトを提供していますwindow functions これは、単一のクエリ自体の両方のタスクを達成するために使用することができます.
    SELECT id, organiser_id, venue_id, scheduled_date, COUNT(*) OVER () AS total_count
    FROM events
    WHERE scheduled_date < NOW()
    LIMIT 10 OFFSET 0;
    
     id | organiser_id | venue_id | scheduled_date | total_count
    ---------+--------------+----------+----------------+-------------
      4 |            6 |        2 | 2021-02-20     |          54
      5 |            4 |        6 | 2021-05-29     |          54
      6 |            4 |        7 | 2021-02-14     |          54
      7 |            1 |        2 | 2021-06-23     |          54
      8 |            2 |       10 | 2021-06-30     |          54
     10 |            1 |       13 | 2021-08-01     |          54
     11 |            5 |        6 | 2021-02-28     |          54
     12 |            4 |        4 | 2021-07-07     |          54
     19 |            3 |        5 | 2021-07-21     |          54
     26 |            4 |        1 | 2021-02-12     |          54
    (10 rows)
    
    私たちはOVER 以下の節では、エンジンが前の関数を評価するために、次のように記述することができます.PARTITION BY あなたがペアになる方法のようにLIMIT and OFFSET 一緒に節.
    我々は、カバーPARTITION BY 将来の投稿の節ですが、この場合COUNT(*) 関数は、すべての行に対して、PARTITION BY への節ORDER 節の節LIMIT 10 OFFSET 10 出力だけを返すLIMIT 10 なしでOFFSET 条項.
    したがって、COUNT(*) OVER () は、WHERE さらにセットされるスーパーセットに含まれるLIMIT あなたはすでにあなたのための総カウントを保持する専用の列があります.😄

    結論


    これは、一度はどこにでも使用して戦略を使用して一度は、このような複数のページ化された選択の間に挿入されていない場合は、これは効率的ではないときに私の銀行のアプリを常に維持するときは、月は、給料のクレジット記録を参照してください開始されます.私の銀行機関がこの戦略を使用するならば、その悪いもの(現在少なくとも).😛
    銀行リフレッシュのような複数のページ化された選択の間に頻繁に挿入することができますか、または私が私のMorning履歴を費やすケースのために、これはあなたがあなたのデータベース・プロセスを最適化することができて、どのようにそのフロントエンド版を印象づけることができるかです.😉

    参考文献

  • MySQL - Information Functions
  • Postgres - SQL_CALC_FOUND_ROWS equivalent
  • Postgres - Window Functions
  • MariaDB - sql_calc_found_rows
  • MariaDB - found_rows()
  • 更なる読書

  • MySQL to deprecate SQL_CALC_FOUND_ROWS and FOUND_ROWS
  • To SQL_CALC_FOUND_ROWS or not to SQL_CALC_FOUND_ROWS?