After reading your question multiple times I have the impression that you might be mixing one or other memory management issue. Be it from the OS perspective or the SQL Server Memory Management perspective.
Let's approach this step by step and then roll it up from the back again.
Paging Issues and SQL Server
If SQL Server is really encountering issues with SQL Server memory being paged out to disk, then you will find the following error message in the ERRORLOG file of your SQL Server instance related to error 17890
:
A significant part of sql server process memory has been paged out.
This may result in a performance degradation. Duration: #### seconds.
Working set (KB): ####, committed (KB): ####, memory utilization: ##%.
Reference: Memory Management Architecture Guide (Microsoft | SQL Docs)
Reference: Server Memory Configuration Options (Microsoft | SQL Docs)
This issue can be related to the Lock Pages in Memory setting and is documented in the Microsoft article Memory Management Architecture Guide (Microsoft | SQL Docs). The solution would be to turn on the option Lock Pages in Memory, but ...
Only used when necessary, namely if there are signs that sqlservr process is being paged out.
...which would be mentioned in the ERRORLOG. (scroll back up for the error message)
Max Server Memory
To see what is consuming SQL Server buffer cache on your instance, run the following command:
Buffer Statement Grouped
SELECT
(CASE WHEN ([database_id] = 32767)
THEN N'Resource Database'
ELSE DB_NAME ([database_id]) END) AS [DatabaseName],
COUNT (*) * 8 / 1024 AS [MBUsed],
SUM (CAST ([free_space_in_bytes] AS BIGINT)) / (1024 * 1024) AS [MBEmpty]
FROM sys.dm_os_buffer_descriptors
GROUP BY [database_id];
GO
The statement will ...
Returns information about all the data pages that are currently in the SQL Server buffer pool. The output of this view can be used to determine the distribution of database pages in the buffer pool according to database, object, or type.
Reference: sys.dm_os_buffer_descriptors (Transact-SQL) (Microsoft | SQL Docs)
Before I ran the Buffer Statement Grouped query against an instance hosting the AdventureWorks2012 and AdventureWorks2012DW database, I made sure that my instance had some data stored in the buffer cache by issuing the following command:
select 'SELECT * FROM ' + ss.name + '.' + sao.name + ' where 1=1' from sys.all_objects sao join sys.schemas as ss on ss.schema_id = sao.schema_id
where sao.type = 'U' and sao.is_ms_shipped = 0
...and then running the output against the AdventureWorks2012 and AdventureWorks2012DW database. I then queried the sys.dm_os_buffer_descriptors
management view with the script and received the following results:
DatabaseName | MBUsed | MBEmpty
----------------------|--------|---------
AdventureWorksDW2012 | 103 | 6
AdventureWorks2012 | 95 | 9
SQL Server had stored some of the data I had queried in the SQL Server buffer. Question is would it change if I increased the max server memory (MB) setting? My current setting was 1024 MB. I then increased the value to 2048 MB:
sp_configure 'show advanced options', 1
go
reconfigure
go
sp_configure 'max server memory (MB)', 2048
go
reconfigure
Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
Configuration option 'max server memory (MB)' changed from 1024 to 2048. Run the RECONFIGURE statement to install.
...and queried the sys.dm_os_buffer_descriptors
management view again:
DatabaseName | MBUsed | MBEmpty
----------------------|--------|---------
AdventureWorksDW2012 | 2 | 0
AdventureWorks2012 | 3 | 0
As you can see, altering the max server memory (MB) setting will flush out the SQL Server buffer cache (data) and other, which can be observed in the ERRORLOG file:
2020-01-30 08:33:17.17 spid55 Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.74 spid55 Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.75 spid55 Configuration option 'max server memory (MB)' changed from 1024 to 2048. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.75 spid55 SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Object Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
2020-01-30 08:35:23.75 spid55 SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'SQL Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
2020-01-30 08:35:23.75 spid55 SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Bound Trees' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
Because the SQL Server cache has been flushed, any queries that now have to be run against the database(s), will have enough memory to:
- create fresh execution plans
- store data in memory
You're instance is able to keep up with the user request up until the point where normal user requests might hinder the queue you are talking about, because SQL Server will optimize the available memory based on the queries hitting the database engine.
Paging and SQL Server
Microsoft writes:
Microsoft SQL Server performs dynamic memory management based on the memory requirements of the current load and activities on the system. On Windows, SQL Server can use the memory notification mechanisms that are provided by the QueryMemoryResourceNotification Windows API. Based on this information from the QueryMemoryResourceNotification Windows API or from the memory calculation, SQL Server responds to the current memory situation on a specific system. This provides the following benefits:
- The system does not page out the working set of the SQL Server process.
- The necessary database pages are available in memory to reduce physical I/O needs.
For more information, see the "Dynamic memory management" topic and the "Server memory options" topic in SQL Server Books Online.
Reference: How to reduce paging of buffer pool memory in SQL Server (Microsoft Support)
Important
Caution
There is a Workaround and a How to troubleshoot this problem section in the above article. Please read the How to troubleshoot this problem first!!
If you are encountering issues of SQL Server paging out the working set data, then this will be commented in the ERRORLOG. You can then determine if you need to troubleshoot the SQL server and possibly configure Lock Pages in Memory.
However, if your max server memory (MB) setting is too low, then you might encounter the ERRORLOG message, but can relieve the issue by increasing the max server memory (MB) setting without having to set the Lock Pages in Memory privilege.
I reproduced this issue on my SQL Server instance by:
- decreasing the max server memory (MB)
- performing huge selects
- checking the ERRORLOG
- increasing the max server memory (MB) setting again
I observed that paging was in fact an issue when I didn't have sufficient memory:
2020-01-30 09:13:30.69 spid23s A significant part of sql server process memory has been paged out. This may result in a performance degradation. Duration: 0 seconds. Working set (KB): 177204, committed (KB): 347808, memory utilization: 50%.
2020-01-30 09:13:33.69 spid23s A significant part of sql server process memory has been paged out. This may result in a performance degradation. Duration: 0 seconds. Working set (KB): 164596, committed (KB): 334896, memory utilization: 49%.
As can be seen looking at the time stamps, these tests were performed in sequence on my SQL Server instance
Increasing the memory again, reduced paging.
Solution
- If you have memory to spend, increase the max server memory (MB) parameter. This can reduce paging (as shown in my case).
- If you don't have memory to spend, follow the How to troubleshoot this problem in the article I referenced.
- If all else fails, consider setting the Lock Pages in Memory configuration.
Answering Your Question
What is controlling SQL Server's page file usage? SQL Server or Windows?
I'll quote again from the Memory Management Architecture document I referenced and emphasise some points:
The default memory management behavior of the SQL Server Database Engine is to acquire as much memory as it needs without creating a memory shortage on the system. The SQL Server Database Engine does this by using the Memory Notification APIs in Microsoft Windows.
When SQL Server is using memory dynamically, it queries the system periodically to determine the amount of free memory. Maintaining this free memory prevents the operating system (OS) from paging. If less memory is free, SQL Server releases memory to the OS. If more memory is free, SQL Server may allocate more memory. SQL Server adds memory only when its workload requires more memory; a server at rest does not increase the size of its virtual address space.
SQL Server release memory to the Operating System based on the Operating System's requirements/needs. They work hand-in-hand.