cmemthread wait
cpu가 많고, cmemthread wait 가 많을때 traceflag 8048 을 enable 하면 메모리 할당 경합을 줄일 수 있다.
이는 numa 나 suma(bios 에서 numa 를 disable 한 경우나 tf 로 numa 를 disable 한 경우)로 구성된 메모리 파티션을 per cpu로 메모리 관리 정책 변경이다.
heap memory 를 할당 할 때 SQL 은 mutex, spin lock (spin lock 을 돌다가 포기하면 back-off 가 발생한다.) 을 이용해 critical section을 관리한다. 그러므로, SQL Server 가 메모리 할당 전략을 NUMA 의 per node 로 되어 있고 4개의 물리 소켓 프로세서가 있다면, 4개의 thread 만 동시에 메모리를 할당 할 수 있을것이다. 그러나, 메모리 구분 전략을 per cpu 로 바꾼다면, 동시에 많은 thread 가(최대 core 갯수만큼) heap 에 메모리를 할당 할 수 있으므로 메모리 할당경합이 줄 수 있을것이다.
tempdb 를 물리 코어수 만큼 다 나누더라도 동시에 임시테이블이나 worker table 을 만드는 횟수가 적다면, tempdb 를 나누는 것이 도움이 되지 않는다. 이와 마찬가지로 memroy 할당이 동시에 많지 않다면, 이러한 TF 는 도움이 되지 않는다. 생각해 봐라. core 가 80개 인데 tempdb 80개로 나누고 있겠는가? 아니다. 적절히 동시에 사용하는 수만큼만 나누어 주면 된다. latch 경합이 발생하는 경우 파일을 나누는 것은 도움이 된다. 그러나, 물리 i/o 가 문제가 되는 경우에는 균형할당 알고리즘에 의해 random i/o 만 증가 시킬 수 있다. tempdb 를 나누는 것은 latch 경합을 줄이는 것이고 물리적 하드디스크의 random i/o 를 줄이는 것이 아니다.
위와 같이 cmemthread 경합이 발생하는 대표적인 경우는 ad-hoc 쿼리가 많을 때 일듯하다. SQL Server 는 쿼리 플랜을 만들때 메모리 할당이 필요하고, 이 때 파라메터 바인딩된 쿼리를 쓰지 않았을 경우 각각의 ad-hoc 쿼리가 모두 컴파일 될 필요가 있다. 이 때 이러한 유형(cmemthread)의 경합이 발생할 수 있다. 이러한 쿼리를 발생시키는 쿼리가 ISV 에서 만든 솔루션이라면 파라메터 바인딩된 쿼리로 고치지 못할 것이다. 이러한 경우 TF8048은 강력한 무기가 될 수 있을듯 하다.
SELECT
type, pages_in_bytes,
CASE
WHEN (0x20 = creation_options & 0x20) THEN 'Global PMO. Cannot be partitioned by CPU/NUMA Node. TF 8048 not applicable.'
WHEN (0x40 = creation_options & 0x40) THEN 'Partitioned by CPU.TF 8048 not applicable.'
WHEN (0x80 = creation_options & 0x80) THEN 'Partitioned by Node. Use TF 8048 to further partition by CPU' (이때만 효과가 있음)
ELSE 'UNKNOWN'
END
from sys.dm_os_memory_objects
order by pages_in_bytes desc
Trace flag 8015 http://blogs.msdn.com/b/psssql/archive/2010/04/02/how-it-works-soft-numa-i-o-completion-thread-lazy-writer-workers-and-memory-nodes.aspx
http://blogs.msdn.com/b/psssql/archive/2012/12/20/how-it-works-cmemthread-and-debugging-them.aspx