Search This Blog

Showing posts with label SQL Server performance tuning. Show all posts
Showing posts with label SQL Server performance tuning. Show all posts

SQL Server performance tuning Tips


Monitor SQL Server Performance and Activity

select @@connections as 'Total Login Attempts'
-- Returns the number of connections or attempted connections

select @@cpu_busy as 'CPU Busy', getdate() as 'Since'
-- Returns CPU processing time in milliseconds for SQL Server activity

select @@idle as 'Idle Time', getdate() as 'Since'
-- Returns SQL Server idle time in milliseconds

select @@io_busy as 'IO Time', getdate() as 'Since'
-- Returns I/O processing time in milliseconds

select @@pack_received as 'Packets Received'
-- Returns the number of input packets read from the network by SQL Server

select @@pack_sent as 'Packets Sent'
-- Returns the number of output packets written to the network by SQL Server

select @@packet_errors as 'Packet Errors'
-- Returns the number of network packet errors for SQL Server connections

select @@timeticks as 'Clock Ticks'
-- Returns the number of microseconds per CPU clock tick

select @@total_errors as 'Total Errors', getdate() as 'Since'
-- Returns the number of disk read/write errors encountered by SQL Server

select @@total_read as 'Reads', getdate() as 'Since'
-- Returns the number of disk reads by SQL Server

select @@total_write as 'Writes', getdate() as 'Since'
-- Returns the number of disk writes by SQL Server

select * from fn_virtualfilestats(null,null)
-- Returns input/output statistics for data and log files

Rebuilding all indexes on a table and specifying options

If you are planning rebuild index  to use this statement below , you must run update statistics statement after rebuild index. Statistics are always updated when you rebuild index.  But STATISTICS_NORECOMPUTE=ON disable the auto update statistics from updating the specific statistics for an index (or column-level statistics)

-- Try to avoid this options
USE AdventureWorks2012;
GO
ALTER INDEX ALL ON Production.Product
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
              STATISTICS_NORECOMPUTE = ON);
GO

UPDATE STATISTICS (Production.Product)
GO

(OR)

Alternatively you can use below options

-- By default STATISTICS_NORECOMPUTE = OFF

USE AdventureWorks2012;
GO
ALTER INDEX ALL ON Production.Product
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
              STATISTICS_NORECOMPUTE = OFF);

--  For single index options
ALTER INDEX[IDX_INDEX_NAME] ON [dbo].[Product]   REBUILD WITH (STATISTICS_NORECOMPUTE=OFF)


Source: Microsoft needs to correct this page.
http://technet.microsoft.com/en-us/library/ms188388.aspx

How to remove Key Lookup on your query plan

Key Lookup was Introduced in SQL Server 2005 Service Pack 2, the Key Lookup operator is a bookmark lookup on a table with a clustered index. The Argument column(Predicate) contains the name of the clustered index and the clustering key used to look up the row in the clustered index. Key Lookup is always accompanied by a Nested Loops operator. Query performance can be improved by adding a covering index on nonclustered index.

When you found a key lookup for a query execution plan window. The easiest way to remove key lookup from the execution plan is to add covering index for the specific column into that non-clustered in the table.

use AdventureWorks
go
sp_helpindex [Sales.SalesOrderDetail]

--Find list of index currently on table  [Sales.SalesOrderDetail]

index_name index_description index_keys
AK_SalesOrderDetail_rowguid nonclustered, unique located on PRIMARY rowguid
IX_SalesOrderDetail_ProductID nonclustered located on PRIMARY ProductID
PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID clustered, unique, primary key located on PRIMARY SalesOrderID, SalesOrderDetailID

-- Run the this two queries with display estimated execution plan
Select ProductID 
From Sales.SalesOrderDetail 
Where ProductID = 776
go
select ProductID, OrderQty 
from Sales.SalesOrderDetail 
where ProductID =776
go

As you can see Key Lookup operator for second query. How would you simply remove from the query plan.?  Add an QrderQty column into INCLUDE on non clustered Index idx_SalesOrderDetail.



As you can see the Key Lookup has been removed from display execution plan

Source : Craig Freedman thoughts from his blog
Bookmark lookup is not a cheap operation.  Assuming (as is commonly the case) that there is no correlation between the non-clustered and clustered index keys, each bookmark lookup performs a random I/O into the clustered index.  Random I/Os are very expensive.  When comparing various plan alternatives including scans, seeks, and seeks with bookmark lookups, the optimizer must decide whether it is cheaper to perform more sequential I/Os and touch more rows using an index scan or a seek with a less selective predicate that covers all required columns or to perform fewer random I/Os and touch fewer rows using a seek with a more selective predicate and a bookmark lookup.


Partitioning existing table SQL2008R2

Create partioning for existing table with more than 1120962253 rows today. It was amazing to see the query performance.

Make sure to create a files groups ([PARTITION_FG1], [PARTITION_FG2],[PARTITION_FG3],[PARTITION_FG4] for partioned table
Also you can create Separate file group for Non-Clustered Index  on different driveNCINDEX_FG5

USE [TestDB]
GO
--Step 1. Creating a Partition Function
CREATE PARTITION FUNCTION PFSvrId_Left (numeric (10,0))
AS RANGE LEFT FOR VALUES (399, 499, 699, 799);
--The result for this RANGE LEFT assignment is:
--{min … 399}, {400 … 499}, {500 … 699}, {799 … max}


--Step 2. Creating a Partition Scheme
CREATE PARTITION SCHEME SvrIdScheme
AS PARTITION  PFSvrId_Left
TO ([PARTITION_FG1], [PARTITION_FG2],[PARTITION_FG3],[PARTITION_FG4],[PRIMARY])

--Step 3. CREATE CLUSTERED INDEX 1
-- Now create a Partitioned using clustered index based Scheme
CREATE CLUSTERED INDEX [idx_LoadID] ON [dbo].[MyTable]
(
      [M_ID] ASC
) ON SvrIdScheme(s_id)

-- Step 4.  CREATE NONCLUSTERED INDEX 2 on Separate file group 
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [PK_MyTable] PRIMARY KEY NONCLUSTERED
(  [t_id] ASC,  [s_id] ASC
)ON [NCINDEX_FG5]
GO

--– Check for new partitions
SELECT partition_id, object_id, partition_number, rows
FROM sys.partitions
WHERE object_id = OBJECT_ID('MyTable')
 GO

How to detect a Torn Page

SQL Server maintains suspect page information in a msdb database new system table : suspect_pages.When the database engine reads a database page containing a CHECKSUM or TORN PAGE (error 824), the page is considered suspect and Page ID number is recorded in the suspect_pages table.

SELECT db_name(database_id) DatabaseName , file_id , page_id , last_update_date
FROM msdb.dbo.suspect_pages
WHERE event_type=3

Torn pages can also be detected by reviewing the output from a DBCC CHECKDB command.

How to check AUTO_CREATE_STATISTICS is enabled for database

use master
go
SELECT name AS 'Name',
    is_auto_create_stats_on AS "Auto Create Stats",
    is_auto_update_stats_on AS "Auto Update Stats",
    is_read_only AS "Read Only"
FROM sys.databases
WHERE database_ID > 4;
GO
-- Also you can check list of statistics created on your database
use Mydb
go
SELECT OBJECT_NAME(s.object_id) AS object_name,
    COL_NAME(sc.object_id, sc.column_id) AS column_name,
    s.name AS statistics_name
FROM sys.stats AS s Join sys.stats_columns AS sc
    ON s.stats_id = sc.stats_id AND s.object_id = sc.object_id
WHERE s.name like '_WA%'
ORDER BY s.name;

When updating statistics with UPDATE STATISTICS or sp_updatestats, Microsoft recommend keeping
AUTO_UPDATE_STATISTICS set to ON so that the query optimizer continues to routinely update statistics.

Find Page Life Expectancy (PLE) value for default SQL Server instance

SELECT cntr_value AS [Page Life Expectancy], @@servername AS Server
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Page life expectancy'
AND [object_name] = 'SQLServer:Buffer Manager'

Note: If you get cntr_value is less than 300 then, that means

An average page life expectancy of 300 is 5 minutes. Anything less could indicate memory pressure or missing indexes, or a cache flush.

Advanced Troubleshooting with Extended Events

Paul S.Randal has written wonderful article on Technet about Troubleshooting SQL Server using extended events in SQL Server 2008.
  • Why troubleshooting is necessary
  • Troubleshooting tools in SQL Server
  • Overview and architecture of Extended Events
  • Using Extended Events
Source : http://technet.microsoft.com/en-us/magazine/2009.01.sql2008.aspx

How to capture deadlock on your sql error logs regularly

--Find the trace flag currently running

DBCC TRACESTATUS(-1)
GO
-- Enable Trace ID 1204 for deadlock
DBCC TRACEON (1204)
GO




Set Max memory on SQL Server

Always set max server memory option to maximum physical memory of the server

exec sp_configure 'min server memory (MB)', 500
go

-- Error
Msg 15123, Level 16, State 1, Procedure sp_configure, Line 51
The configuration option 'min server memory (MB)' does not exist, or it may be an advanced option.

-- Solution
exec sp_configure 'show advanced options', 1
go
RECONFIGURE
go
exec sp_configure 'min server memory (MB)' ,500
go
exec sp_configure 'max server memory (MB)' , 'your server physical memory'
go

Fill Factor option for when Create Index or Rebuild Index
When creating a index or rebuilt, The FILL-FACTOR value determines the percentage of space on each leaf-level page to be filled with data. It is important to set the fill-factor value for each index. In practice a fill-factor value is set to 80 means that 20 percent of each level-level page will be left empty.

USE AdventureWorks2008;

GO
CREATE NONCLUSTERED INDEX IDX_WorkOrder_ProductID
ON Production.WorkOrder(ProductID)
WITH (FILLFACTOR = 80,
PAD_INDEX = ON);
GO

How to find the Index with Fragmentation issue

SELECT db.name AS databaseName ,  ps.OBJECT_ID AS objectID
, ps.index_id AS indexID,  ps.partition_number AS partitionNumber
, ps.avg_fragmentation_in_percent AS fragmentation , ps.page_count
FROM sys.databases db
INNER JOIN sys.dm_db_index_physical_stats (NULL, NULL, NULL , NULL, N'Limited') ps
ON db.database_id = ps.database_id
WHERE ps.index_id > 0
AND ps.page_count > 100 AND ps.avg_fragmentation_in_percent > 30
OPTION (MaxDop 1)

How to Enable the Lock Pages in Memory Option on Windows Server

The Windows policy Lock Pages in Memory option is disabled by default. This privilege must be enabled to configure Address Windowing Extensions (AWE). This policy determines which accounts can use a process to keep data in physical memory, preventing the system from paging the data to virtual memory on disk. On 32-bit operating systems, setting this privilege when not using AWE can significantly impair system performance. Locking pages in memory is not normally required on 64-bit operating systems. You will need to enable this right on 64-bit operating systems only when using Large Page Memory support or to configure SQL Server such that the Buffer Pool memory does not get paged out. Use the Windows Group Policy tool (gpedit.msc) to enable this policy for the account used by SQL Server 2005 Database Engine. You must be a system administrator to change this policy.


To enable the lock pages in memory option

--------------------------------------------------------------------------------
1.On the Start menu, click Run. In the Open box, type gpedit.msc.
The Group Policy dialog box opens.
2.On the Group Policy console, expand Computer Configuration, and then expand Windows Settings.
3.Expand Security Settings, and then expand Local Policies.
4.Select the User Rights Assignment folder.
The policies will be displayed in the details pane.
5.In the pane, double-click Lock pages in memory.
6.In the Local Security Policy Setting dialog box, click Add.
7.In the Select Users or Groups dialog box, add an account with privileges to run sqlservr.exe.

Active SQL Server connections


SP_WHO2

These are just a few helpful DMV requests, returning details regarding the active SQL Server connections.  Keep in mind, user sessions are >= session_id 51.


Report all the connections to SQL Server, returning one row for each:
  SELECT
    connection_id,
    session_id,
    client_net_address,
    auth_scheme
 FROM
    sys.dm_exec_connections


Report each session connected to SQL Server, similar to sp_who2:
 SELECT
    session_id,login_name,
    last_request_end_time,cpu_time
 FROM
    sys.dm_exec_sessions
 WHERE
    session_id >= 51
 ORDER BY
    last_request_end_time DESC


Report details for what each connection is actually doing:
  SELECT
    session_id,
    status,
    command,
    sql_handle,
    database_id
 FROM
    sys.dm_exec_requests
 WHERE
    session_id >= 51

SQL Server: Performance Tuning (Understanding Set Statistics Time output)

In the last post we have discussed about Set Statistics IO and how it will help us in the performance tuning. In this post we will discuss about the Set Statistics Time which will give the statistics of time taken to execute a query.

Let us start with a example.

USE AdventureWorks2008
GO
            DBCC dropcleanbuffers
            DBCC freeproccache

GO
SET STATISTICS TIME ON
GO
SELECT * 
    FROM Sales.SalesOrderHeader SOH INNER JOIN  Sales.SalesOrderDetail SOD ON
            SOH.SalesOrderID=SOD.SalesOrderID 
    WHERE ProductID BETWEEN 700 
        AND 800
GO
SELECT * 
    FROM Sales.SalesOrderHeader SOH INNER JOIN  Sales.SalesOrderDetail SOD ON
            SOH.SalesOrderID=SOD.SalesOrderID 
    WHERE ProductID BETWEEN 700 
        AND 800





















There aretwo select statement in the example .The first one is executed after clearing the buffer. Let us look into the output.


SQL Server parse and Compile time : When we submit a query to SQL server to execute,it has to parse and compile for any syntax error and optimizer has to produce the optimal plan for the execution. SQL Server parse and Compile time refers to the time taken to complete this pre -execute steps.If you look into the output of second execution, the CPU time and elapsed time are 0 in the SQL Server parse and Compile time section. That shows that SQL server did not spend any time in parsing and compiling the query as the execution plan was readily available in the cache. CPU time refers to the actual time spend on CPU and elapsed time refers to the total time taken for the completion of the parse and compile. The difference between the CPU time and elapsed time might wait time in the queue to get the CPU cycle or it was waiting for the IO completion. This does not have much significance in performance tuning as the value will vary from execution to execution. If you are getting consistent value in this section, probably you will be running the procedure with recompile option.


SQL Server Execution Time: This refers to the time taken by SQL server to complete the execution of the compiled plan. CPU time refers to the actual time spend on CPU where as the elapsed time is the total time to complete the execution which includes signal wait time, wait time to complete the IO operation and time taken to transfer the output to the client.The CPU time can be used to baseline the performance tuning. This value will not vary much from execution to execution unless you modify the query or data. The load on the server will not impact much on this value. Please note that time shown is in milliseconds. The value of CPU time might vary from execution to execution for the same query with same data but it will be only in 100's which is only part of a second. The elapsed time will depend on many factor, like load on the server, IO load ,network bandwidth between server and client. So always use the CPU time as baseline while doing the performance tuning.

Activity monitor, Script to find Head blocker- SQL Server 2005, 2008 and later


This is very handy useful script in production environment. Even the activity monitor does  the same but when there is high server high activity then your activity monitor hangs and do not respond. Also it is not recommended to use activity monitor for long in production environments as it uses high resources.

SELECT
   [Session ID]    = s.session_id,
   [User Process]  = CONVERT(CHAR(1), s.is_user_process),
   [Login]         = s.login_name,  
   [Database]      = ISNULL(db_name(p.dbid), N''),
   [Task State]    = ISNULL(t.task_state, N''),
   [Command]       = ISNULL(r.command, N''),
   [Application]   = ISNULL(s.program_name, N''),
   [Wait Time (ms)]     = ISNULL(w.wait_duration_ms, 0),
   [Wait Type]     = ISNULL(w.wait_type, N''),
   [Wait Resource] = ISNULL(w.resource_description, N''),
   [Blocked By]    = ISNULL(CONVERT (varchar, w.blocking_session_id), ''),
   [Head Blocker]  =
        CASE
            -- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others
            WHEN r2.session_id IS NOT NULL AND (r.blocking_session_id = 0 OR r.session_id IS NULL) THEN '1'
            -- session is either not blocking someone, or is blocking someone but is blocked by another party
            ELSE ''
        END,
   [Total CPU (ms)] = s.cpu_time,
   [Total Physical I/O (MB)]   = (s.reads + s.writes) * 8 / 1024,
   [Memory Use (KB)]  = s.memory_usage * 8192 / 1024,
   [Open Transactions] = ISNULL(r.open_transaction_count,0),
   [Login Time]    = s.login_time,
   [Last Request Start Time] = s.last_request_start_time,
   [Host Name]     = ISNULL(s.host_name, N''),
   [Net Address]   = ISNULL(c.client_net_address, N''),
   [Execution Context ID] = ISNULL(t.exec_context_id, 0),
   [Request ID] = ISNULL(r.request_id, 0),
   [Workload Group] = ISNULL(g.name, N'')
FROM sys.dm_exec_sessions s LEFT OUTER JOIN sys.dm_exec_connections c ON (s.session_id = c.session_id)
LEFT OUTER JOIN sys.dm_exec_requests r ON (s.session_id = r.session_id)
LEFT OUTER JOIN sys.dm_os_tasks t ON (r.session_id = t.session_id AND r.request_id = t.request_id)
LEFT OUTER JOIN
(
    -- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as
    -- waiting for several different threads.  This will cause that thread to show up in multiple rows
    -- in our grid, which we don't want.  Use ROW_NUMBER to select the longest wait for each thread,
    -- and use it as representative of the other wait relationships this thread is involved in.
    SELECT *, ROW_NUMBER() OVER (PARTITION BY waiting_task_address ORDER BY wait_duration_ms DESC) AS row_num
    FROM sys.dm_os_waiting_tasks
) w ON (t.task_address = w.waiting_task_address) AND w.row_num = 1
LEFT OUTER JOIN sys.dm_exec_requests r2 ON (s.session_id = r2.blocking_session_id)
LEFT OUTER JOIN sys.dm_resource_governor_workload_groups g ON (g.group_id = s.group_id)--TAKE THIS dmv OUT TO WORK IN 2005
LEFT OUTER JOIN sys.sysprocesses p ON (s.session_id = p.spid)
ORDER BY s.session_id; 

Memory configuration in SQL server and break up of memory utilized by SQL server

In this post I would like to explain memory configuration option and memory utilization pattern in SQL server.I have seen many people worrying about the memory utilization (in task bar or through other monitoring tool) on a box where SQL server is installed. I have also seen people becoming  panic after seeing the alert 
The threshold for the Memory\% Committed Bytes In Use performance counter has been exceeded. The value that exceeded the threshold is: 90.5850397745768 

from SCOM (System Center Operations Manager) .I hope this post will help them to find an answer.

In SQL server the Physical memory utilization is controlled by following two parameters available through sp_configure 
  • min server memory (MB)
  • max server memory (MB)
These two parameters control only the memory utilized by the buffer pool(bpool). In SQL server bpool is the biggest consumer of the memory.There are other component which  consume memory apart from bpool.
Below is the list major component which use memory apart from bpool.
  • SQL Mail 
  • COM/OLE components loaded in SQL Server
  • Prepared document using sp_xml_preparedocument
  • Linked Server
  • Backup/Restore
  • SQL CLR
It is very important to define these two parameter especially in the case like SQL server is running on a box where other applications are also running,multiple instances are installed on the same machine,installation over cluster environment,etc

min server memory (MB): The min server memory setting define the lower limit of the memory available for buffer pool. On start up of SQL server, the buffer pool does not immediately acquire the amount of memory specified in min server memory. It starts with memory required to initialize. As the workload increase, it keeps acquiring memory.Once it acquired the amount of memory mentioned the min server memory configuration, bpool acquire more memory depends on the memory availability on the server and max server memory settings.bpool never drops the memory below the level specified in the min server memory once it acquired. The total amount of memory consumed by the bpool is completely depends on the workload. On a SQL instance that is not processing many request may never reach min server memory limit.By default this value set to 0.
max server memory(MB): The max server memory define the upper limit for the bpool. It will never  acquire the memory more than value specified in the max sever memory setting even if there is lot memory available on the server.Once it is reached the limit specified and if there is memory request from OS, bpool will keep releasing memory till it reaches the min server memory. The  default this value for this is 2147483647 (2TB).

To understand it in much better way, look at the Fig 1 where the green(40 GB) and orange(20 GB) portion  are occupied by bpool of INST1 as per the configuration settings of max server memory (60 GB) by leaving 4GB for OS ,other processes and non bpool components. Assume that we have installed one more instance on the same server with configuration setting as mentioned in the Fig 2.Now to satisfy the min server memory setting of INST2 (20 GB) ,INST1 is forced to release the memory which was above min memory setting by keeping only 2GB(orange portion). Now INST2 satisfied it min server memory configuration by leaving only 42 GB for INST1 and 2GB for OS,other processes and non bpool component.In later point of time if OS required more memory to perform some action , it can grab maximum of 2 GB from the INST2.If that is not enough for OS other task , you can feel overall degradation of the performance of the physical server.

Memory Configuration Consideration : I have seen many servers which running on the default value for these two parameters. It may not make harm on the stand alone server which dedicated to single instance of SQL server. In the case of multiple instances on the same server, we have to configure these two parameter in all the instances to guarantee  that all instances and OS will have minimum memory to process its workload. A typical setting in our environment where we run three instance on the same box is given below. 






The sum of min server is restricted to 27 GB by leaving 5 GB for OS and other process.Max server memory is configured in such a way that the , SQL instances can make use of the 5GB if the OS does not requires that.Also note that SQL server is very efficient in releasing the memory if there is a memory pressure from OS  but only  till the min server memory configuration.

It is more important to configure memory settings appropriately  in the cluster environment. Instances might work very smoothly when it running on its own preferred owner node.In case of some  issues , if one instance failed over to another node (assuming it is active-active cluster or multiple instances are failed over to the passive node in case of active-passive cluster environment), the performance of the instances might affect depends on the setting. So it is important to configure these value to make sure the multiple instances can run on the same node with out much memory crunch. Think about a scenario of two node active-active cluster and each node has 64GB memory. SQL instances on these nodes are configured with 50 GB as min server memory and 60GB as max server memory. What will happen if one of the instance failed over to another node ? I am sure  you will be able to figure out what will happen and how to resolve the issue.

Break up of memory consumed by SQL server: Below are the various objects that consume memory in  SQL server

















This Memory Utilized by various object in SQL server.sql will list the memory consumed by the various object in SQL server. From the listing you can easily identify that the Bpool is the biggest consumer of the memory. It is interesting to know the amount of bpool memory utilized by each database.The Bpool utilization by databases.sql will give you the details of Bpool memory utilized by each databases.It will be more interesting to know the details of objects in each database that consume bpool space.The  Memory Utilized by objects in db.sql will give that statistics.


Memory Utilized by various object in SQL server.sql
/*
Author : Nelson John A
Description :List the memory utilized by various objects in SQL server

*/

IF OBJECT_ID('tempdb..#MemoryTable') IS not NULL
 drop table #MemoryTable 
 GO
create table #MemoryTable (SeqNo int,MemoryUsagedesc varchar(1000),MemoryUsage decimal(20,2))

DECLARE @pg_size INT, @Instancename varchar(50)


SELECT @pg_size = low from master..spt_values where number = 1 and type = 'E'
SELECT @Instancename = LEFT([object_name], (CHARINDEX(':',[object_name]))) FROM sys.dm_os_performance_counters WHERE counter_name = 'Buffer cache hit ratio'
insert into #MemoryTable 
SELECT 1,'Total Server physical memory' ,physical_memory_in_bytes/1048576.0 as [Physical Memory_GB] FROM sys.dm_os_sys_info

insert into #MemoryTable 
SELECT 2 ,'BPool Committed' ,(bpool_committed*8)/1024.0 FROM sys.dm_os_sys_info

insert into #MemoryTable 
SELECT 3 ,'BPool Commit Target' ,(bpool_commit_target*8)/1024.0  FROM sys.dm_os_sys_info

insert into #MemoryTable 
SELECT 4 ,'BPool Visible' ,(bpool_visible*8)/1024.0   FROM sys.dm_os_sys_info

insert into #MemoryTable 
SELECT 5,'Connection Memory' ,cntr_value/1024.0  FROM sys.dm_os_performance_counters WHERE counter_name = 'Connection Memory (KB)'

insert into #MemoryTable 
SELECT 6, 'Lock Memory',cntr_value/1024.0 FROM sys.dm_os_performance_counters WHERE counter_name = 'Lock Memory (KB)'

insert into #MemoryTable 
SELECT 7,'Memory for dynamic SQL cache' ,cntr_value/1024.0 FROM sys.dm_os_performance_counters WHERE counter_name = 'SQL Cache Memory (KB)'
insert into #MemoryTable 
SELECT 8,'Memory for Query Optimizer',cntr_value/1024.0 FROM sys.dm_os_performance_counters WHERE counter_name = 'Optimizer Memory (KB)'

insert into #MemoryTable 
SELECT 9,'memory used for hash, sort and create index operations',cntr_value/1024.0 FROM sys.dm_os_performance_counters WHERE counter_name = 'Granted Workspace Memory (KB) '

insert into #MemoryTable 
SELECT 10,'memory consumed by cursors',cntr_value/1024.0 FROM sys.dm_os_performance_counters WHERE counter_name = 'Cursor memory usage' and instance_name = '_Total'

insert into #MemoryTable 
SELECT 11,'Plan Cache ',(cntr_value*@pg_size)/1048576.0 FROM sys.dm_os_performance_counters WHERE object_name=@Instancename+'Plan Cache' and counter_name = 'Cache Pages'  and instance_name = '_Total'


insert into #MemoryTable 
SELECT 12,'buffer pool (includes data, free, and stolen)', (cntr_value*@pg_size)/1048576.0 as Pages_in_MB FROM sys.dm_os_performance_counters WHERE object_name= @Instancename+'Buffer Manager' and counter_name = 'Total pages' 

insert into #MemoryTable 
SELECT 13,'Buffer Pool Data pages' ,(cntr_value*@pg_size)/1048576.0 FROM sys.dm_os_performance_counters WHERE object_name=@Instancename+'Buffer Manager' and counter_name = 'Database pages' 

insert into #MemoryTable 
SELECT 14,'Buffer Pool Free pages',(cntr_value*@pg_size)/1048576.0 FROM sys.dm_os_performance_counters WHERE object_name=@Instancename+'Buffer Manager' and counter_name = 'Free pages'


insert into #MemoryTable 
SELECT 15,'Buffer Pool Reserved pages ',(cntr_value*@pg_size)/1048576.0 FROM sys.dm_os_performance_counters WHERE object_name=@Instancename+'Buffer Manager' and counter_name = 'Reserved pages'

insert into #MemoryTable 
SELECT 16,'Buffer Pool Stolen pages ', (cntr_value*@pg_size)/1048576.0 FROM sys.dm_os_performance_counters WHERE object_name=@Instancename+'Buffer Manager' and counter_name = 'Stolen pages'

select * from #MemoryTable  order by SeqNo ;



Bpool utilization by databases.sql 
/*
Author : Nelson John A
Description :Bpool utilization by databases

*/

With CTE_BP(DatabaseName, BufferSizeInMB )
as
(
SELECT 
case when DB_NAME(b.database_id) is null then 'Resource DB' else DB_NAME(b.database_id) end  AS database_name
,(cast(COUNT(*) as decimal(20,2)) * 8192.00) / (1024.00 * 1024) AS buffer_count_MB
FROM  sys.dm_os_buffer_descriptors AS b 
GROUP BY  b.database_id
)
select * from CTE_BP order by BufferSizeInMB desc

Memory Utilized by objects in db.sql

Use DATABASE_NAME
GO
SELECT 
name AS TableName, 
IndexName,
IndexTypeDesc,
(cast(COUNT(*) as decimal(20,2)) *8.0)/1024 AS 'cached_page_Size(mb)',
COUNT(*) AS 'cached_pages_count'

FROM sys.dm_os_buffer_descriptors AS bd
INNER JOIN
(
SELECT 
Allocation.name, 
Allocation.index_id,
Allocation.allocation_unit_id, 
Allocation.OBJECT_ID,
ind.name IndexName, 
ind.type_desc IndexTypeDesc
FROM
(
SELECT 
OBJECT_NAME(p.OBJECT_ID) AS name,
p.index_id ,
au.allocation_unit_id, 
p.OBJECT_ID
FROM sys.allocation_units AS au
INNER JOIN sys.partitions AS p ON au.container_id = p.hobt_id
AND (au.type = 1 OR au.type = 3)
UNION ALL
SELECT 
OBJECT_NAME(p.OBJECT_ID) AS name,
p.index_id, 
allocation_unit_id, 
p.OBJECT_ID
FROM sys.allocation_units AS au INNER JOIN sys.partitions AS p ON au.container_id = p.partition_id 
AND au.type = 2
) AS Allocation
LEFT JOIN sys.indexes ind ON ind.index_id = Allocation.index_id AND ind.OBJECT_ID = Allocation.OBJECT_ID 
) AS sysobj ON bd.allocation_unit_id = sysobj.allocation_unit_id
WHERE database_id = DB_ID()
GROUP BY name, index_id, IndexName, IndexTypeDesc
ORDER BY TableName


Hope now you have better idea about the memory configuration and utilization in SQL server.  Please feel free to pass your comments.