Windows 2012 R2上のSQL Server 2012 SP3 Enterprise Editionを使用しています。
SQLログでこれらのエラーを確認しました。
ページの割り当てに失敗しました:FAIL_PAGE_ALLOCATION 1
2016-06-14 04:28:27.44 spid175エラー:701、重大度:17、状態:123。
2016-06-14 04:28:27.44 spid175このクエリを実行するには、リソースプール 'default'にシステムメモリが不足しています。
2016-06-14 04:28:27.44サーバーエラー:17300、重大度:16、状態:1.(パラメーター:)。フォーマット中にエラーが発生したため、エラーは簡略モードで出力されます。トレース、ETW、通知などはスキップされます。
2016-06-14 04:28:27.44サーバーエラー:17300、重大度:16、状態:1.(パラメーター:)。フォーマット中にエラーが発生したため、エラーは簡略モードで出力されます。トレース、ETW、通知などはスキップされます。
2016-06-14 04:28:27.44 spid131エラー:701、重大度:17、状態:123。
私の知る限り、ある時点でメモリが不足したようです。
メモリ不足の原因を突き止める方法はありますか?MEMORYCLERK_SQLQERESERVATIONS
はかなり高いですが、誰がそれが何のためにあるのか知っていますか?
MEMORYCLERK_SQLQERESERVATIONS (node 0) KB
---------------------------------------- ----------
VM Reserved 0
VM Committed 0
Locked Pages Allocated 0
SM Reserved 0
SM Committed 0
Pages Allocated 22599824
編集:サーバーに32 GBのRAM=があり、28がSQL Serverに割り当てられています。最大メモリ設定は28 GB、最小サーバーメモリは8 GBです。
ErrorLog出力へのリンクは次のとおりです。 ErrorLog
これがsys.dm_os_process_memory出力へのリンクです。 Query Output
待機タイプへのリンク: WaitTypes
メモリ使用量が多いと思われるときに実行しました。
SELECT * FROM sys.dm_exec_query_memory_grants(grant_timeはnull)
結果: memory_grants
SELECT mg.granted_memory_kb、mg.session_id、t.text、qp.query_plan FROM sys.dm_exec_query_memory_grants AS mg CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle)AS t CROSS APPLY sys.dm_exec_query_plan(mg.plan_handle)AS qp ORDER BY 1 DESCオプション(MAXDOP 1)結果: QueryMemGrants
SELECT top 50 t.text、cp.objtype、qp.query_plan、cp.usecounts、cp.size_in_bytes> as [Bytes Used in Cache] FROM sys.dm_exec_cached_plans AS cp JOIN sys.dm_exec_query_stats AS qs ON cp.plan_handle = qs.plan_handle CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle)AS qp CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle)AS t WHERE qp.query_plan.exist( 'declare namespace> n = "http://schemas.Microsoft.com/sqlserver/ 2004/07/showplan ";> // n:MemoryFractions ')= cp.size_in_bytes desc OPTIONによる1オーダー(MAXDOP 1)
結果: CachedMemGrants
Sys.dm_exec_requestsからGranted_query_memory、session_id、commandを選択します結果: dm_exec_requests
実行されていたクエリの1つからのクエリプランのXML: QueryPlan
エラーログの出力にはdbcc memorystatus
ダンプがあり、私が気付いたのは
Process/System Counts Value(in Bytes)
---------------------------------------- ----------
Available Physical Memory 1217605632---1.1 G
Available Virtual Memory 140627167866880
Available Paging File 5656502272
Working Set 305238016
Percent of Committed Memory in WS 99
Page Faults 27923310
System physical memory high 0
System physical memory low 0
Process physical memory low 1--Memory Low
Process virtual memory low 0
2016-06-14 04:28:27.41 Server
使用可能な物理メモリが非常に少ないことに注意してください。バッファプールにメモリがほとんどありませんでした
より多くのメモリを消費している店員について
MEMORYCLERK_SQLQERESERVATIONS (node 0) KB
---------------------------------------- ----------
VM Reserved 0
VM Committed 0
Locked Pages Allocated 0
SM Reserved 0
SM Committed 0
Pages Allocated 22599824 --21.5 G
Page Life Expectancy 64
MEMORYCLERK_SQLQERESERVATIONS
が21.5 Gを使用している場合、最大サーバーメモリが28 Gのサーバーで、これは間違いなく問題です。これがOOM状態の原因です。
MEMORYCLERK_SQLQERESERVATIONSとは
これは、実行中に Sort または hash operations を含むクエリに割り当てられたメモリを追跡するSQL Serverのメモリクラークです。これらの演算子は、クエリの最大のメモリコンシューマになります。
これによるOOMエラーの理由
並べ替えとハッシュ操作を含むクエリが実行されると、並べ替えまたはハッシュ演算子を含む元のクエリプランに基づいて予約リクエストが行われます。次にクエリが実行されると、メモリが要求され、SQL Serverはメモリの可用性に応じて、その要求を部分的または完全に許可します。このようなリクエストへのメモリ割り当てを追跡する「MEMORYCLERK_SQLQERESERVATIONS」という名前のメモリ担当者(会計士)がいます。今あなたのシナリオでは次のことが起こっている可能性があります
クエリが要求するメモリの許可が多すぎるため、SQL Serverは限られた量しか提供できません。この制限された量は「必要なメモリ」と呼ばれ、クエリの実行中およびクエリの実行中に開始されます。これは、メモリ要件が大きくSQL Serverができないためです。リソースプールにメモリがなかったため、それを指定すると、クエリはOOMエラーで失敗します。クエリの実行時に必要なメモリは「追加メモリ」と呼ばれます
バグが修正されました SQL Server 2012 Sp1 CU4 クエリが大量のメモリ許可を要求したため、大幅に遅くなるか、その後OOMエラーで失敗しました。バグが再浮上した可能性は、QEReservationsがすべてのバッファープールを占有したという事実を考慮すると除外できません。
店員がすでにメモリの90%を使用しているため。新しいクエリに必要なメモリが使用できず、クエリはOOMエラーで失敗します。
テーブルとインデックスの統計が歪んでいるため、オプティマイザは準最適なプランを作成する必要があり、実際に必要とされるよりもはるかに多くのメモリ許可を要求し、問題が発生します。
最後に、SQL Serverで実行されるクエリには、いくつかの深刻な調整が必要です。
このように Blogs.msdn記事
開発者は実際にソート/ハッシュ操作について何ができますか?
クエリの書き換えについて言えば、大量のメモリが付与される可能性のあるクエリでの注意事項を次に示します。
クエリがSORT演算子(すべてを含むリストではない)を使用する理由:
ORDER BY (T-SQL) GROUP BY (T-SQL) DISTINCT (T-SQL) Merge Join operator selected by the optimizer and one of the inputs of the Merge join has to be sorted because a clustered index is
その列では使用できません。
クエリがハッシュ一致演算子を使用する理由(すべてを含むリストではない):
JOIN (T-SQL) – if SQL ends up performing a Hash Join. Typically, lack of good indexes may lead to the most expensive of join operators
–ハッシュ結合。クエリプランを見てください。
DISTINCT (T-SQL) – a Hash Aggregate could be used to perform the distinct. Look at query plan. SUM/AVG/MAX/MIN (T-SQL)– any aggregate operation could potentially be performed as a Hash Aggregate . Look at query plan. UNION – a Hash Aggregate could be used to remove the duplicates.
問題をさらに理解するには、以下のクエリの出力を質問に追加する必要があります。 Paul Randal Wait stats query の出力も追加してほしい。クエリのソースは このブログ です。ブログを読むことをお勧めします。
SELECT * FROM sys.dm_exec_query_memory_grants where grant_time is null
--Find who uses the most query memory grant:
SELECT mg.granted_memory_kb, mg.session_id, t.text, qp.query_plan
FROM sys.dm_exec_query_memory_grants AS mg
CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS t
CROSS APPLY sys.dm_exec_query_plan(mg.plan_handle) AS qp
ORDER BY 1 DESC OPTION (MAXDOP 1)
--Search cache for queries with memory grants:
SELECT t.text, cp.objtype,qp.query_plan
FROM sys.dm_exec_cached_plans AS cp
JOIN sys.dm_exec_query_stats AS qs ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS t
WHERE qp.query_plan.exist(‘declare namespace n=”http://schemas.Microsoft.com/sqlserver/2004/07/showplan“; //n:MemoryFractions’) = 1
システム上で実行されているクエリを確認してほしい他にいくつかあります。
Select granted_query_memory,session_id,command from sys.dm_exec_requests
これは、システムで実行されているクエリにどのくらいのメモリが許可されているかを示します。
あなたが持っているXMLの実際の実行計画を見ることができればMemoryGrant=xxxxx
あなたは高価なクエリのためにこの値を集めることができます。
上記のすべては、クエリに問題があるかどうか、またはそれが実行のために多くのメモリを要求している理由に関して他の問題があるかどうかを示します。
[〜#〜]編集[〜#〜]
貼り付けたさまざまなクエリ出力から。
requested_memory_kb
は、多数のクエリが約5Gであることがわかります。これは大規模なメモリ許可であり、理想的には数MBである必要があります。 required_memory_kb
は約5 MBで、granted_query_memory
はNULLであることに注意してください。これは、SQL Serverがクエリを開始するための最小メモリを提供できるだけで、クエリに追加のメモリを提供できないためです。実行結果のクエリはOOMエラーで失敗します。
大量のメモリを要求するクエリのクエリコストも高いため、統計が歪んでいるか、クエリの記述が不十分であると思います。他の可能性は、適切なインデックスでサポートされていないクエリです。このような巨大なメモリの付与を要求するクエリの数は、数が多いです。
上記のクエリについては、granted_query_memory
を参照してください。すべてGBです。実行中の最初の3つのクエリは、メモリの約50%を使用する約15Gのメモリを使用しました。 SQL Serverでは、何らかの方法でメモリを必要とする何百万ものプロセスが実行されるため、3つのクエリが使用可能なメモリの50%を使用しているかどうかを確認できますOOMの問題が発生するはずです。
ソリューション
上記のスクリーンショットの最初の4つのクエリを調整することを真剣に検討する必要があります
少なくとも1週間に1回はインデックスの再構築と統計の更新を実行し、統計の偏りがオプティマイザに不適切な計画の作成を強制しないようにしてください。
リソースガバナーを使用して、リソースプールとワークロードグループを作成し、このプールで大量のメモリ許可を要求しているクエリを実行します。パラメータrequest_max_memory_grant_percentage
を使用して、メモリ要求を制限できます。例を this Blog に示します。これは、すべてのクエリを調整するまでの代替方法です。