Showing posts with label stolen memory. Show all posts
Showing posts with label stolen memory. Show all posts

Friday, April 17, 2020

SQL Server 2017 cu17 Columnstore Workload OOMs Part 2: Whoever Smelt It, Dealt It?

This blog post is under construction...

This blog post is part of a series started yesterday with the post linked immediately below.

SQL Server 2017 cu17 ColumnStore Workload OOMs Part 1
https://sql-sasquatch.blogspot.com/2020/04/sql-server-2017-cu17-columnstore.html



Error investigation can be informed by one of two paradigms:
I think of the first paradigm as "whoever smelt it, dealt it."
The second paradigm is "the bearer of bad news."
Sometimes to reach the correct conclusion, the events and surrounding timeline must be examined from both viewpoints.

Whoever Smelt It, Dealt It

This article provided some needed laughter yesterday when I read it.  Its not directly relevant to the matter at hand... but its worth a chuckle.


We Asked Scientists Whether He Who Smelt It Really Dealt It

https://www.vice.com/en_us/article/ypa5x5/we-asked-scientists-whether-he-who-smelt-it-really-dealt-it

What the heck does this sophomoric idea have to do with OOMs, or any error type?

Consider this simplistic example.  The error is a direct result of the action by this session.  This session's action alone was sufficient to warrant the "divide by zero" error message.
This session smelt the error message, because this session dealt the divide by zero.


As it relates to OOMs, consider the OOM described in this blog post.
SQL Server 2019 Scalar UDF inlining - OOM in some cases
https://sql-sasquatch.blogspot.com/2019/11/sql-server-2019-udf-inlining-oom-in.html

A single session in isolation executing a query with an ugly UDF that triggers UDF inlining is sufficient to consume enough [Optimizer Memory] to result in the OOMs described in the post.  Yes, its a (fixed in CU2) bug, but the activity by that individual session realizes the risk presented by the bug.  That session  smelt it by way of the OOM, after that session dealt it by using an ugly inlined UDF.

OK.  Now let's focus on the OOMs I'm currently dealing with.  In SQL Server, if an OOM can be properly described as "whoever smelt it, dealt it" the memory activity must be attributable to the session that received the error and only that session.

One way for that to be the case is for that session to be running in isolation - no other user sessions on the instance.  That's not the case in observations of the OOMs I'm concerned with.  Each occurrence of these OOMs happens to be when there are multiple concurrent user sessions.

Another way for the memory activity to be attributable to the specific session that received the error is if the memory type is specifically and solely allocated to the session.  Connection memory works like that.  Connection memory is within [Total Server Memory] but individual sessions have private access to small chunks of it.  Optimizer memory works that way, too.  So, too, does the used portion of query memory grants.  All of the memory in [Total Server Memory] that can be individually attributed to sessions is within [Stolen Server Memory].  But not all [Stolen Server Memory] can be individually attributed to sessions.  (For example, consider the plan cache within [Stolen Server Memory].  Although an individual session inserts a plan into cache, while the plan is cached other sessions can use it.  And a cached plan can stay in cache after the session that originally inserted it has ended.)

It just so happens I have some graphs. Each of the red vertical lines below is an OOM.  Usually in a graph like this I have [Stolen Server Memory] at the top of the stacked graph, with [Free Memory] and [Database Cache Memory] below it.  Like this...



But since I want to focus on [Stolen Server Memory] I want it at the bottom of the stack for now, like this...



In the workloads I am concerned with, the largest portion of individually attributable [Stolen Server Memory] is the amount of granted query memory that is used for sort/hash/columnstore compression at any given time.  If all user workload groups are associated with the Default Resource Pool, that amount is [\SQLServer:Memory Manager\Granted Workspace Memory (KB)] - [\SQLServer:Memory Manager\Reserved Server Memory (KB)].  If user Resource Pools other than Default during the timeperiod of concern, the information should be gathered from sys.dm_exec_query_memory_grants and/or sys.dm_exec_query_resource_semaphores to account for the total granted and total reserved memory.

Fortunately for me, on this day the only resource pools present were Default and Internal.  A little bit easier path.

The next graph is the amount of granted memory (not necessarily already used), with [\SQLServer:Memory Manger\Total Server memory (KB)] included on the same graph for scale.

First of all, I'll point out that the total granted memory is not very high compared to the target server memory. Also, the yellow box indicates high points for granted memory that occurred without errors, while errors occurred later with lower levels of granted memory.


Let's zoom in a little for better visibility.  This graph is granted memory - but it doesn't indicate how much of the granted memory is used.



Because on the Default resource pool was in play, layering the reserved memory in front of granted memory gives an idea of the used query memory.  In the graph below, the exposed dark green is the portion of [\SQLServer:Memory Manager\Granted Workspace Memory (KB)] which is used. 



well, well...



well, well....






Date,Source,Severity,Message
12/21/2019 03:15:35,spid83,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:17:51,spid79,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:24:14,spid51,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:36:41,spid73,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:43:01,spid89,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:47:00,spid55,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670319<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:50:43,spid57,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34670740<nl/>Simulated                                    166692<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                    0
12/21/2019 03:54:08,spid73,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639426<nl/>Simulated                                    250762<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 03:56:07,spid73,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639426<nl/>Simulated                                    250762<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 03:58:37,spid73,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639426<nl/>Simulated                                    250762<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:00:43,spid52,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639426<nl/>Simulated                                    250762<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:03:27,spid70,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639437<nl/>Simulated                                    250718<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:05:45,spid74,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639437<nl/>Simulated                                    250718<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:09:38,spid70,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      34639440<nl/>Simulated                                    250706<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:15:57,spid107,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      21670985<nl/>Simulated                                   2875695<nl/>Simulation Benefit                                0<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070
12/21/2019 04:23:20,spid94,Unknown,Memory Broker Clerk (Column store object pool)      Pages<nl/>---------------------------------------- ----------<nl/>Total                                      21660293<nl/>Simulated                                   2892211<nl/>Simulation Benefit                       0.0000000000<nl/>Internal Benefit                                  0<nl/>External Benefit                                  0<nl/>Value Of Memory                                   0<nl/>Periodic Freed                                    0<nl/>Internal Freed                                84070

well, well...


Memory Broker Clerk (Column store object pool)
Time               Pages            kb
03:15:35           34670319         277362552
03:17:51           34670319         277362552
03:24:14           34670319         277362552
03:36:41           34670319         277362552
03:43:01           34670319         277362552
03:47:00           34670319         277362552
03:50:43           34670740         277365920
03:54:08           34639426         277115408
03:56:07           34639426         277115408
03:58:37           34639426         277115408
04:00:43           34639426         277115408
04:03:27           34639437         277115496
04:05:45           34639437         277115496
04:09:38           34639440         277115520
04:15:57           21670985         173367880
04:23:20           21660293         173282344

a haw haw haw...

Thursday, October 25, 2018

SQL Server 2016 Memory Accounting Part II: Another Suspicious Example

Originally published 2018 October 25
Updated 2020 December 15
*****
I wanted to update this blog post with a link to a fix that corrects the memory double-counting described here (and the condition that leads to it).

KB4536005 - Improvement: Fix incorrect memory page accounting that causes out-of-memory errors in #SQLServer #SQLServer 2019 CU2 #SQLServer 2017 CU20 #SQLServer 2016 SP2 CU15
*****


tl;dr - No answers yet but perhaps a cleaner picture of the puzzle.

A few months ago I shared a puzzle I've been looking at.  The example i shared is from 4 vNUMA node VM, where the equation [database + stolen + free = total] holds true for the instance but does NOT hold true on one or more SQLOS memory nodes associated with the vNUMA nodes.  Further, although sum(node database cache) is equal to instance-wide database cache, and sum(node free memory) is equal to instance-wide free memory... sum(node stolen memory) may greatly exceed instance-wide stolen memory. Eventually i realized that memory is being double-counted as database cache on one node and as stolen memory on another node.  More details at the link.

SQL Server 2016 Memory Accounting: A Suspicious Surprise
http://sql-sasquatch.blogspot.com/2018/07/sql-server-2016-memory-accounting.html

Recently I looked at a 2 vNUMA node VM and saw the same memory conditions.  Even though I don't yet understand what leads to this condition (or what leads out of it), I wanted to share these graphs because the 2 vNUMA node example is maybe a little cleaner. And I think these graphs maybe look a little nicer :-)

Nothing extraordinary when looking at instance-wide measures from memory manager.


 

And, even though that's a really large share of stolen memory on node 000, [database + stolen + free = total] as expected.



But... whoa!! What's going on on node 001? The [database + stolen + free] goes way over total.




Adding free memory from the two nodes yields the free memory number from memory manager.




Adding database cache from the two nodes yields the database cache number from memory manager.




Omigarrrssshhh!!  Adding stolen memory from the two nodes yields a number sometimes much greater than the stolen memory reported by the memory manager.






So now there are two cases where sums of node values are unexpectedly unexpectedly greater than their corresponding values.

I expect these two equations to hold true, and they are being transgressed:

   "\SQLServer:Memory Node(001)\Stolen Node Memory (KB)"
+ "\SQLServer:Memory Node(000)\Stolen Node Memory (KB)"
= "\SQLServer:Memory Manager\Stolen Server Memory (KB)"

   "\SQLServer:Memory Node(001)\Database Node Memory (KB)"
+ "\SQLServer:Memory Node(001)\Stolen Node Memory (KB)"
+ "\SQLServer:Memory Node(001)\Free Node Memory (KB)"
= "\SQLServer:Memory Node(001)\Total Node Memory (KB)"

Let's compare the differences between the sum of components and the aggregate value (both of these differences are expected to be zero, or near zero due to timing issues).




Huh. The differences from expected values are equal.  Something is causing a varying amount of memory to be counted on node 001 as database cache memory AND double-counted on node 000 as stolen memory.

I've asked about this on twitter at the #sqlhelp tag.  No answers yet - that's not surprising.  i tend to look at SQL Server memory in a rather particular - maybe even peculiar - way 😀 .  If i don't have more of a clue by  PASS Summit, i plan to take this to SQL Clinic to find out what's up.

https://twitter.com/sqL_handLe/status/1055181887180804098 https://twitter.com/sqL_handLe/status/1055181887180804098

Why do i care?  Because with tuned CCI workloads, memory-related waits (and CPU time related to memory latency) becomes more important than it was in the past with pure rowstore queries.  And there are sometimes still foreign memory issues like this...



In order for me to tune the system optimally to match the workload (and vice versa), I need a better understanding of memory behavior, potential performance costs, and interventions which can change behavior.

All right - that's all for today!  Ciao!!