数日前、外国人が書いたプログラムを見たことがありますが、そのプログラムは MySQL クエリで Limit キーワードを多用しており、非常に興味を持ちました。なぜなら、私の印象では、Limit キーワードは MySQL データベースでよく使用されているように思えたからです。プログラマーはこれを使用してクエリ ページングを実行します (もちろん、これは優れたクエリ最適化でもあります)。Oracle では通常、
SELECT * FROM ( SELECT a1.*, rownum rownum_
FROM testtable a1
WHERE rownum > 20)
WHERE rownum_ このステートメントは、テーブル内の testtable 20 ~ 1000 レコードをクエリできます。ネストされたクエリが必要ですが、これはあまり効率的ではありません。MySQL の実装を見てみましょう。
SELECT * FROM testtable a1 limit 20,980;
これは、testtable テーブルのレコードに 21 を返します (20 + 980 =)。 1000件のレコード。
実装構文は確かに単純ですが、ここで 2 つの SQL ステートメントの効率について話したい場合、MySQL の Limit オプションを解釈する方法が多数あり、速度の違いがあるため、比較するのは困難です。さまざまな意味で巨大であるため、このステートメントの単純さから誰がより効率的であるかを判断することはできません。
でも、プログラマーにとっては、メンテナンスコストが低いので、シンプルな方が良いんです(笑)。
この Limit の構文について説明します。
SELECT ……. --Select ステートメントのその他のパラメーター
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
ここでの offset はオフセット Shift (このオフセットの開始アドレスは 1 ではなく 0 です。これは間違いやすいです) 名前が示すように、開始点から離れた位置であり、行数も非常に単純です。返されるレコード数の制限。
例: SELECT * FROM testtable a limit 10,20 where ….
これにより、結果は 10 行後に where 条件を満たす 20 個のレコードを返すことができます (10 行自体を含む)。
制約がない場合は、10 ~ 29 行のレコードが返されます。
では、これはテーブル全体のスキャンを回避することとどのような関係があるのでしょうか? 以下は、MySQL マニュアルの Limit パラメータ最適化スキャンに関する説明です:
場合によっては、HAVING を使用する代わりに LIMIT オプションを使用すると、MySQL はクエリを異なる方法で処理します。
l LIMIT を使用して行のサブセットのみを選択する場合、MySQL は通常、完全なテーブル スキャンを実行しますが、場合によってはインデックス (ipart 関連) を使用します。
l LIMIT n と ORDER BY を同時に使用すると、MySQL が条件を満たす最初のレコードを見つけた後、テーブル全体をソートするのではなく、ソートが終了します。
l LIMIT n と DISTINCT を一緒に使用すると、MySQL はレコードを見つけた後にクエリを停止します。
l 場合によっては、GROUP BY は、キーを順番に読み取り (またはキーでソート)、キー値が変わるまで要約を計算することで解決できます。この場合、LIMIT n は不要な GROUP を評価しません。
l MySQL は、n 番目の行をクライアントに送信し終わると、残りのクエリを破棄します。
l そして、LIMIT 0 オプションは常にすぐに空のレコードを返します。これは、クエリをチェックし、結果列の列タイプを取得するのに役立ちます。
l 一時テーブルのサイズは、LIMIT # を使用して、クエリを解決するために必要なスペースの量を計算します。