SQL Serverは、バッファキャッシュに十分なスペースがないクエリのデータをどのように処理しますか?


10

私の質問は、SQL Serverが、利用可能な領域よりも多くのデータをバッファキャッシュにプルする必要があるクエリをどのように処理するかです。このクエリには複数の結合が含まれているため、結果セットはこのフォーマットですでにディスク上に存在せず、結果をコンパイルする必要があります。ただし、コンパイル後でも、バッファキャッシュで使用可能な領域よりも多くの領域が必要です。

例を挙げましょう。合計6GBの利用可能なバッファキャッシュスペースを持つSQL Serverインスタンスがあるとします。7GBのデータを読み取る複数の結合を使用してクエリを実行しますが、SQL Serverはこの要求にどのように応答できますか?tempdbにデータを一時的に保存しますか?失敗しますか?ディスクからデータを読み取り、一度にセグメントをコンパイルするだけですか?

さらに、7GBの合計データを返そうとするとどうなりますか?SQL Serverがデータを処理する方法は変わりますか?

私はこれに対処するいくつかの方法をすでに知っていますが、SQL Serverがこのように実行されたときに、SQL Serverがこの要求を内部的に処理する方法に興味があります。

また、この情報はどこかにあると思いますが、見つけるのに失敗しました。


1
簡単に言えば、SQL Serverは作業テーブルと独自の内部処理の結果をtempdbに格納します。ページは必要に応じてディスクから読み取られます。ページは、強制的に取り除かれるか、SQLがページをディスクにコミットする準備ができるまで、メモリに残ります。大規模なクエリを実行すると、tempdbが大きくなります。tempdbがチェックされずに拡大し、ドライブの残りのすべてのスペースを消費するため、クエリがシステムに問題をもたらすことを見てきました。これは100%正確ではないことを知っています。単純に説明しようとしています。データを使用する部分は、そのデータの場所を管理する部分ではありません
datagod

回答:


13

必要に応じてページがメモリに読み込まれ、使用可能な空きメモリがない場合は、変更されていない最も古いページが着信ページに置き換えられます。

つまり、メモリに収まらないほど多くのデータを必要とするクエリを実行すると、多くのページがメモリ内で非常に短い期間しか存続せず、大量のI / Oが発生します。

この影響は、Windowsパフォーマンスモニターの "ページの期待寿命"カウンターで確認できます。そのカウンターの詳細については、https: //sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancyをご覧ください

コメントでは、クエリの結果が使用可能なバッファスペースよりも大きい場合にどうなるかを具体的に尋ねました。最も単純な例をselect * from some_very_big_table;考えてみましょう-テーブルが32GBでありmax server memory (MB)、24GBで構成されていると仮定します。すべての32GBのテーブルデータが一度に1つずつページバッファーのページに読み込まれ、ラッチされます。、ネットワークパケットにフォーマットされ、ネットワーク経由で送信されます。これはページごとに発生します。このようなクエリを同時に300個実行することができ、ブロッキングが発生していないと仮定すると、各クエリのデータは、ページバッファスペースに一度に1ページずつ読み込まれ、クライアントができる限り速くネットワークに送信されます。データをリクエストして使用します。各ページのすべてのデータがネットワークに送信されると、ページのラッチが解除され、すぐにディスクの他のページに置き換えられます。

より複雑なクエリの場合、たとえば複数のテーブルからの結果を集計する場合など、ページはクエリプロセッサが必要とするため、上記とまったく同じようにメモリに読み込まれます。クエリプロセッサが結果を計算するために一時的なワークスペースを必要とする場合は、クエリのプランをコンパイルするときにそのことを事前に認識しSQLOSにワークスペース(メモリ)を要求します。SQLOSは、ある時点で(タイムアウトにならない場合)、そのメモリをクエリプロセッサに許可します。その時点でクエリ処理が再開されます。クエリプロセッサがSQLOSに要求するメモリ量の見積もりを間違えた場合、「ディスクへのスピル」を実行する必要がある場合があります操作。データは一時的な形式でtempdbに一時的に書き込まれます。tempdbに書き込まれたページは、tempdbに書き込まれるとラッチが解除され、他のページをメモリに読み込むためのスペースが確保されます。最終的に、クエリプロセスはtempdbに格納されているデータに戻り、ラッチを使用してページングされ、空きとしてマークされているバッファー内のページに戻ります。

上記の要約では、非常に多くの技術的な詳細が欠落していることは間違いありませんが、SQL Serverがメモリに収まりきらないデータを処理する方法の本質を捉えていると思います。


好奇心から、7GBのデータを取得するクエリの種類は何ですか?これがバッチプロセスであることを願っています。
datagod 2017年

おそらく多くはないでしょうし、あなたが正しいと思いますが、それはうまくいけばバッチプロセスになるでしょう。SQLがそのリクエストをどのように処理するか
ダスティン

5

このシナリオでクエリが正確に何を行うかについて話すことはできませんが、SQL Serverには必要な量に応じていくつかのオプションがあります。

  • データはTempDBに「流出」する可能性があり、これはディスクを使用することになります
  • 古いページをバッファキャッシュから押し出すことができます
  • SQL Serverは、いくつかのページをバッファキャッシュにロードし、それらを使用して、新しいページをローテーションできます。

何が起こるかを知る最良の方法は、開発環境でシナリオを作成して調べることです。


2

私の質問は、SQL Serverが、より多くのデータ量をバッファキャッシュにプルする必要があるクエリをどのように処理してから、利用可能なスペースがあるかです。

この特定の部分に答えるために、これがどのように管理されているかを説明しましょう。ページのサイズは8KBです。大規模なデータセットを要求するクエリを実行し、メモリに多数のページを読み込む必要がある場合、SQL Serverはすべてのページを一度に取得しません。それは特定のページを見つけてメモリに1つずつ8KBページを持ち込み、そこからデータを読み取り、結果を提供します。これは、古いページがフラッシュされる場合にメモリが少ない状況に直面していると想定します。 @Maxのようなディスクが指摘しました。あなたが正しく推測したように、この低いメモリは古いページの削除にいくらかの時間が費やされるため、物事を遅くする可能性があります。これはチェックポイントとレイジーライターの場所です画像になります。Lazywriterは、新しいページをディスクに取り込むために、常に空きメモリがあることを確認するためのものです。空きバッファが不足すると、それがトリガーされ、新しいページになる空きスペースが作成されます。

編集

私はそれを理解しましたが、\ filtering dataに参加していて、それらの結果がキャッシュのサイズを超えた場合、私を少し困惑させる部分が起こります。

結合とフィルタリングのためのメモリは、クエリが実行される前でも決定され、実際にメモリ不足があり、操作の実行に必要なメモリが利用できないと仮定します。SQLServerプロセッサは、「必要なメモリ」を付与します。

必要なメモリ:ソートとハッシュ結合を実行するために必要な最小メモリ。このメモリがないとクエリが開始されないため、必須と呼ばれます。SQLサーバーは、このメモリを使用して内部データ構造を作成し、並べ替えとハッシュ結合を処理します。

したがって、少なくともクエリは実行を開始しますが、実行時に中間結果がTempdbに溢れ、遅くなります。クエリメモリの付与について理解することをお勧めします


私はそれを理解しましたが、\ filtering dataに参加していて、それらの結果がキャッシュのサイズを超えた場合、私を少し困惑させる部分が起こります。戻り値セットを生成するには、データをコンパイルする必要がありますが、戻り値セットはキャッシュのサイズよりも大きくなります。最終結果が生成されるまで、内部的にページをキャッシュに循環させますか?私の考えでは、それがキャッシュを超え、そのような場合には知らないことが、ディスクから読み取るので、それがtempdbのに結果を書き込むということだろう
ダスティン

2
@Dustin私の回答を編集しました。確認してください
Shanky
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.