====== SQLServer Performance ======
* [[:mssqlserver|MS SQL Server]] 성능 측정 / 튜닝
* [[https://docs.microsoft.com/en-us/sql/t-sql/statements/set-showplan-all-transact-sql?view=sql-server-2017|SET SHOWPLAN_ALL (Transact-SQL) | Microsoft Docs]]
* [[https://www.red-gate.com/simple-talk/sql/performance/execution-plan-basics/|Execution Plan Basics - Simple Talk]]
===== 기본 ISOLATION Level =====
SQLServer의 기본 Isolation Level은 **''READ_COMMITTED''**이다.
===== SSMS 에서 Execution Plan 보기 =====
* [[mssqlserver:ssms|SQLServer SSMS SqlServer Management Studio]] 에서 쿼리를 작성하고 쿼리 선택후 **Ctrl+M** 혹은 우클릭후 **Include Actual Execution Plan** 을 체크하고 쿼리를 실행하면 결과 창에 ''Execution plan'' 탭이 생성된다.
* [[https://www.mssqltips.com/sqlservertip/4992/how-to-find-compiled-parameter-values-for-sql-server-cached-plans/|How to find compiled parameter values for SQL Server cached plans]]
===== Index 확인 =====
* ''exec sp_helpindex [tablename]'' : 인덱스 확인
EXEC sys.sp_helpindex @objname = N'User' -- nvarchar(77)
===== No Lock =====
==== 왜 필요한가? ====
* SQL Server는 SELECT를 할 때 SHARED Lock을 건다.
* 이 상황에서는 다른 데서 SHARED Lock을 건 데이터는 읽을 수 있지만 UPDATE/INSERT/DELETE에 의해 EXCLUSIVE Lock이 걸리면 데이터를 읽지 못하고 SHARED Lock 확보시까지 대기한다.
* 또한 매우 실행 시간이 길고 폭넓은 데이터를 선택하는 SELECT 문 실행시에 SHARED Lock이 걸려 있으면 UPDATE/INSERT/DELETE가 EXCLUSIVE Lock을 확보하지 못해서 CUD 작업이 느려질 가능성이 있다.
* 따라서 장시간 걸리고, 여러 행(row)을 탐색하는 SELECT 쿼리의 경우 ''WITH (NOLOCK)''으로 SHARED Lock 없이 쿼리를 수행한다.
==== 실행 방법 ====
* [[http://msdn.microsoft.com/en-us/library/aa213026(v=sql.80).aspx|Locking Hints]]
* ISOLATION을 **''READ_UNCOMMITTED''**로 하거나 모든 FROM절의 테이블 명 뒤에 **''WITH (NOLOCK)''**을 지정한다. 붙여쓰지 말것.
SELECT id
FROM table_a WITH (NOLOCK)
SELECT a.id, b.id
FROM table_a a WITH (NOLOCK), table_b b WITH (NOLOCK)
WHERE a.id=b.id
==== 문제점 ====
* isolation level ''READ_UNCOMMITED''의 모든 문제점을 가지게 된다.
* Dirty Reads : update 중이지만 아직은 commit이 안 된 데이터를 읽게됨. Rollback 시 데이터가 바뀌어버림.
* Phantom Reads : insert/delete 됐지만 아직은 commit이 안 된 데이터를 읽게됨. Rollback 시 데이터가 사라지거나 생김.
* Nonrepeatable Reads : 동일 트랜잭션내에서 동일 쿼리로 데이터를 읽는데 결과가 달라질 수 있다.
* 결론적으로
* **단건 쿼리 혹은 정합성이 중요한 쿼리에서는 사용하지 말 것**
* 실행시간이 긴 통계성 쿼리에서는 거의 필수적으로 필요함.
* CUD 트랜잭션을 짧게 가져갈 수 있도록 항상 노력할 것.
===== UPDATE LOCK =====
* [[http://www.madeiradata.com/role-update-lock-sql-server/|What is the Role of the UPDATE Lock in SQL Server? - Madeira Data Solutions]] UPDATE Lock이 필요한 이유 설명.
* ''UPDATE''문이 업데이트 대상 행을 탐색할 때 SELECT 처럼 SHARED Lock을 사용하면 동시에 둘 이상의 UPDATE 수행시 나중에 EXCLUSIVE Lock으로 변경이 불가하다.(SHARED Lock이 걸린 상태에서는 EXCLUSIVE Lock 불가 원칙)
* 따라서 대상 데이터 탐색시에는 UPDATE Lock을 걸고, 실제 업데이트 수행시 EXCLUSIVE Lock으로 변경한다.
==== 참조 ====
* [[https://learningintheopen.org/2015/09/19/sql-server-execution-plan-warnings-columns-with-no-statistics/|SQL Server – Execution Plan – Warnings – “Columns with no statistics” | Learning in the Open]]
* [[https://www.mssqltips.com/sqlservertip/2470/understanding-the-sql-server-nolock-hint/|Understanding the SQL Server NOLOCK hint]]
* [[https://www.sqlshack.com/locking-sql-server/|All about locking in SQL Server]]