Quantcast
Channel: CodeSection,代码区,SQL Server(mssql)数据库 技术分享 - CodeSec
Viewing all articles
Browse latest Browse all 3160

Using Index Operational Stats to Drill Into High Latch and Lock Waits

$
0
0

In part one of this series on the index operational statistics Dynamic Management Function (sys.dm_db_index_operational_stats) I focused on showing how different query behavior manifested itself in the results returned from querying this Dynamic Management Function (DMF). I also provided you with a generic script to query the full width of columns from that DMF and compared the information that can be derived from this object to that of its companion Dynamic Management View (DMV): sys.dm_db_index_usage_stats. In this next article in the series I’ll be exploring how you identify those objects causing the most issues around lock and latch waits: when you should be concerned enough to look at latching and locking contention as well as what queries to run to identify your main culprits. Finally we’ll look into general points you’ll want to then focus on when it comes to using this information to resolve locking and latches that are unreasonable detractors from a high-performance SQL Server environment.

Recap

For a complete picture of the basics on sys.dm_db_index_operational_stats please review the first article in this series . As a refresher here is how you query sys.dm_db_index_operational_stats and the high-interest columns you should be concerned with understanding thoughout this series:

SELECT *

FROM sys.dm_db_index_operational_stats

(

DB_ID(),

<object_id, if you want to limit to single table or NULL for ALL, NULL>,

<index_id,if you want to limit to single index or NULL for ALL, NULL>,

<partition_id, if you want to limit a partition or NULL for ALL, NULL>

);

You’ll note what may be an odd coding construct for you if you’re unfamiliar with Template Parameters in SQL Server Management Studio. If you’re not familiar with the concept of Template Parameters like I used above please consult thisarticle. The tldr; (too-long-didn’t read) on this is to use the Ctl+Shift+M keyboard shortcut in SQL Server Management Studio (SSMS) when you see the syntax of <some_parameter, description, default_value> to replace those placeholders with values for your specific needs.

If left unadulterated that command will provide you with the results covering all objects (indexes and heaps) and any associated indexes without regards to limiting to a specific partition. Of course by doing so you get a great amount of information returned but it has little value because you have no context for the results. This is why I always end up joining the indexing DMOs to other system views that provide that context for the results (as well as filtering down the rows that are returned as well as the columns I care to see. For that contextual requirement those system views are:

sys.indexes provides information on your SQL Server indexes scoped to the database level, including name, type of index (clustered, non-clustered), uniqueness, and more. sys.objects while I could use the OBJECT_NAME(object_id) system function to return the name of the table or view associated with the object_id exposed by sys.dm_db_index_operational_stats I also need to filter the results because I’m only interested in user objects not those system tables and views that are used internally by SQL Server. To do so I need access to the is_ms_shipped column in sys.objects. While I’m there I may as well return the object name (name column) and type of object (type_desc).

That leaves us with a base structure of:

SELECT O.name AS [object_name]

, O.type_desc AS object_type

, I.name AS index_name

, I.type_desc AS index_type

, ixO.*

FROM sys.dm_db_index_operational_stats

(

DB_ID(),

<object_id, if you want to limit to single table or NULL for ALL, NULL>,

<index_id,if you want to limit to single index or NULL for ALL, NULL>,

<partition_id, if you want to limit a partition or NULL for ALL, NULL>

) AS ixO

INNER JOIN sys.indexes I

ON ixO.object_id = I.object_id

AND ixO.index_id = I.index_id

INNER JOIN sys.objects AS O

ON O.object_id = ixO.object_id

WHERE O.is_ms_shipped = 0;

Of course you’ll want to narrow the column scope down for sys.dm_db_index_operational_stats and also provide some level of filtering through employing search predicates via a WHERE clause but this construct is a good foundation for where we will go from here. For more information on the full range of columns in sys.dm_db_index_operational_stats and their purpose please review that first article in this series. That being said let’s move on and focus on sys.dm_db_index_operational_stats, locking, and latching.

A Very Brief Discussion on Locks and Latches

One of the most important insights you can collect from sys.dm_db_index_operational_stats is focused upon which objects victim to the most latch and lock wait time. Before I continue to show how to identify these contributors to performance degradation I want to take a few paragraphs of your time to give you a primer on just what latches and locks are in terms of Microsoft SQL Server.

Locking is critical in a relational database to allow for transactions to meet the ACID test:

Atomicity : a transaction either needs to complete all its steps or fail to the original state. Consistency : a transaction will always behave in identical fashion. Isolated : transactions are protected from external influence until they complete. Durable : the RDBMS will maintain a record of uncommitted (aka incomplete) transactions in the event of recovery due to failure.

These requirements are met through complex locking processes to ensure that concurrent requests from users do not affect or interact with the outcomes of any other requests. Locks are taken on rows or pages that are involved in open transactions and are released when those transactions are committed or are rolled back. Locks are also taken on objects involved in schema changes to those objects. There is a complex set of rules and logic around locking behavior in Microsoft SQL Server and there are various types of lock modes as well (briefly outlined below):

Shared (S) Locks : involved in read-only operations that don’t modify data. Update (U) Locks : used in UPDATE transactions to prevent multiple transactions from attempting to update the same row concurrently. Exclusive (X) Locks : associated with operations that will change data through an INSERT, UPDATE, or DELETE query to ensure more than one transaction does not attempt to change the same row at the same time as another transaction. Schema (Sch) Locks : granted when an object’s definition is being modified for instance if a column is being added to a table. Intent (I) Locks : these locks are applied to enforce a lock “pecking order” as it were. Consider this a lock that informs the internal engine that a transaction is queued to eventually take the next lock of a type of IS (intent shared), IX (intent exclusive), or SIX (shared, with intent exclusive). Bulk Update (BU) Locks : used in certain conditions when employing bulk copying and supplying locking hints as part of the operation. Key-Range Locks : These locks come into play when using the most restrictive transaction isolation level (serializable see brief explanation of transaction isolation levels in the next par

Viewing all articles
Browse latest Browse all 3160

Trending Articles