블로그 이미지
010-9967-0955 보미아빠

카테고리

보미아빠, 석이 (500)
밥벌이 (16)
싸이클 (1)
일상 (1)
Total
Today
Yesterday

달력

« » 2015.3
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

공지사항

최근에 올라온 글

'2015/03/17'에 해당되는 글 1건

  1. 2015.03.17 wait 생각날때마다.

wait type 과 의미를 천천히 정리해보자

생각날 때 추가해 보도록 하지요....쉽게~ 대충 정리하고 이쁘게 나중에 공식문서로 만들어보죠~

일단은 마구 적습니다. 그리고 나서 하나하나 시나리오를 만들어서 테스트하고 책으로 출간 sqltag book 3?

절대적으로 신뢰하지 말고 테스트 해봐야 합니다. 틀린게 보이면 언제든지 말해주세요~

 

io_completion 은 tempdb 를 사용해 sort spill 을 하거나, 어떤 동기 i/o 오퍼레이션을 할때 나타난다. 이걸 mdf ldf 를 잘 살펴보고 io 를 분산하라고 하면 안된다. io_completion 은 직접적인 data page 의 io 대기가 아니다. tempdb 를 잘 보살펴야 한다. sort 를 제거하던지....

async_io_completion backup alter database create database 등을 할 때 나타날 수 있다.

sleep_task 는 hash match 연산을 하면 일어날 수 있다. 역시 tempdb 를 잘 보살펴야 한다. hash_match 를 안하게 하던지

async_network_io 는 select 하는 데이터양이 많아 네트워크로 보내는 데이터가 많으면 일어날 수 있다. 데이터를 줄이던지 fetch count 를 적절히 크게 하던지 등등


using System;

using System.Collections.Generic;

using System.Data;

using System.Data.SqlClient;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Threading;




namespace ConsoleApplication3

{

    class Program

    {


        static void Main(string[] args)

        {

            SqlNetTest sqlNetTest = new SqlNetTest();

            for (int i = 0; i < 5; i++)

            {

                sqlNetTest.execute();    

            }

            

        }

    }


    class SqlNetTest

    {

        private List<NetTestResult> netTestResults = new List<NetTestResult>();


        private string ConnectionString

        {

            get

            {

                return "Data Source=xxxxxx;Initial Catalog=xxxxx;User ID=xxxxxx;Password =xxxxx";

            }

        }


        public void execute()

        {

            this.netTestResults = usp_netTest(this.ConnectionString);

            foreach (var a in netTestResults)

            {

                Console.WriteLine("name : {0}, type {1}", a.name, a.type);

            }

         

        }


        private List<NetTestResult> usp_netTest (string ConnectionString)

        {

            List<NetTestResult> netTestResults = new List<NetTestResult>();

            using (SqlConnection conn = new SqlConnection(ConnectionString))

            {

                conn.Open();

                using (SqlCommand cmd = conn.CreateCommand())

                {

                    cmd.CommandText = "dbo.usp_netTest";

                    cmd.CommandType = CommandType.StoredProcedure;

                    SqlDataReader read = cmd.ExecuteReader();

                    while (read.Read())

                    {

                        NetTestResult netTestResult = new NetTestResult();

                        netTestResult.name = read.IsDBNull(read.GetOrdinal("name")) ? "" : read.GetString(read.GetOrdinal("name"));

                        netTestResult.type = read.IsDBNull(read.GetOrdinal("type")) ? "" : read.GetString(read.GetOrdinal("type"));

                        netTestResults.Add(netTestResult);

                        Thread.Sleep(100);

                    }

                    read.Close();

                }

                conn.Close();

            }

            return netTestResults;

        }



    }


    public class NetTestResult

    {

        public string name { get; set; }

        public string type { get; set; }

    }

}




-- 이하 sql script
alter proc usp_netTest
as
select cast(name as char(8000)) name, type from sysprocesses  

이렇게 테스트를 한다고 치면, client cursor 이며 결과셋이 작으면 sql server 의 net buffer 에 있는 결과를 다 가져가 버린다. 시간은 수 ms 나 0초가 나온다. 그런데 결과를 일부러 크게 만들어서 sql net buffer 를 다 채우고도 나갈 결과가 더 있는 경우 클라이언트가 다시 요청할때 비워진 버퍼를 sql 이 채우게 될것이다. 이것이 async network io 대기이며, 이것은 클라가 천천히 루프를 돌거나 (임의로 threadsleep 을 준 경우나) 대역폭이 가득차 빨리빨리 요청하더라도 sql 의 net buffer 를 빨리 비우지 못하는 경우일 것이다. 


oledb 는 연결된 서버나 자신의 sql server 외 연결된 데이터 억세스에서 대기가 일어난 경우이다.

latch_xx 는 비 데이터페이지의 대기이다. 메모리 동기화를 위해서 일어나는 대기이다 디스크가 빠르던 느리던 상관없다.

sos_schedulder_yield cpu 를 많이 쓰는 경우 일어나는 대기이다. 사용할 quantum time 을 다 쓰고 scheduler 를 양보할 때 나타난다.  4ms 동안 하나의 logical core 를 다 쓰고 다시 resource wait 나 runnable queue 에 들어가는 경우이다. 수 us 쓰고 나갈꺼라고 생각했는데 비선점점형 스케줄링에 의한 강제양보까지 기다린다니 얼마나 많이 cpu 를 쓰겠는가? 

resource_semaphore memory grant 에 시간이 걸릴때 이다. 메모리를 늘이거나 메모리를 안쓰게 하거나 메모리를 적게쓰게 튜닝한다. 아무리 메모리가 많아도 oltp 는 어쩌고 저쩌고 나도 안다.......쿨럭~ 쉽게 가자고~

cmemthread 역시 메모리 동기화 문제이다. enter critical section exit critical section 으로 동기화 하는데 오랜 시간이 걸린 경우이다. 생각해보라 1) 특정 메모리 영역이 가득차 있고 추가 메모리를 할당할수 없는 상태에서 메모리를 달라고 하면 enter critical section 한 뒤에 메모리를 받을수가 없다. 아니면 2) numa node 당 메모리를 줄 수 있는 부분이 있는데 이 부분을 core 단위로 분리하면 실제 메모리가 있는 상황에서는 동기화 문제를 효과적으로 분배할 수 있다. tempdb iam gam sgam 대기 걸리면 tempdb 쪼개잖아~ 그럼 확 빨라지는 경우를 생각해 봐라

writelog 로그 플러시 시간이 오래 걸리는 경우이다. 이건 disk sub-system 이 병목이 되는지 살펴보고 더 많은 로그를 써야 한다면 데이터베이스를 쪼개서 더 많은 ldf 파일을 쓰도록 하는 방법이 있다. 또는 안 쓰는 인덱스를 지워 트랜젝션 로그를 적게 쓰도록 하면 된다. 혹은 버전을 올린다. 버전을 올리면 더 빨라진다. 무슨버전에서 바뀌었는지 기억이 나지 않는다......아는사람 알려주기~

cxpacket 병렬처리에서 thread 별로 일할 데이터를 골고부 배분하지 못하면 이 대기가 크게 나타날 수 있다. 왜냐하면 코디네이터 하나는 전체 처리기간동안 cxpacket 대기를 찍을것이고, 일꾼들 중 1개 thread 에 100개의 일량을 받고 나머지 3개 thread 에 일량을 받지 못하거나 너무 적게 받았다면 이 대기는 무척 커질수 있다. 코디네이터 100 + 일꾼 3 * 100(99) 의 대기가 발생한다. (한넘을 열심히 일하잖아 ^^) 그런데, 4개의 thread 에 동일하게 일량이 배분되면 코디네이터 25 의 대기가 발생한다. 일량 배분 알고리즘과 강제 일량 분배에 대해서는 쿼리테크닉이 필요하다. 

threadpool 이것은 worker thread 가 소진되어 thread 를 할당받지 못할경우 발생할 수 있다. max worker thread 를 늘여주거나 병렬처리나 lock 을 줄여 thread가 소진되지 않도록 쿼리를 잘 짠다. 

pageiolatch_xx 이건 뭐 디스크 열라게 긁어서 그런거다 쿼리를 효율적으로 바꾸어 읽어야 할 데이터만 읽도록 하던지 메모리를 늘여 디스크에서 안 읽게 하던지 디스크를 빠르게 하던지 선택의 폭은 다양하다 

checkpoint_queue  체크포인트 끝부터 체크포인트 시작까지 대기시간 (체크포인트 하고있는 시간은 빠진다) 하루종일 체크포인트 치고 있으면 이 시간이 짧을것이다. (안부장님) 

logmgr_queue 이것은 i/o 병목이라고 보지 않는다. 그냥 다른넘들도 잘 트랜젝션 로그 쓰기를 시도하고 있구나 정도의 참고수치가 될 듯 하다. 다른 워커가 로그 블럭이 비워지기를 기다리고 있는것을 나타내며 기다리는 아이 몇 넘 * 시간 으로 증가한다. 


Used by the background worker "Log Writer" to wait on a queue for requests to flush log blocks to the transaction log. This is an "optional" wait type see Important Notes section in blog You should be able to safely ignore this wait type unless you believe a problem exists in processing log blocks to flush to the transaction log. 


This wait type is not a wait indicating I/O bottlenecks. It is only for waiting for other workers to request log block flushes. Note that on SQL Server 2005 this wait type will not show up in sys.dm_exec_requests because the Log Writer task does not show up there.


logbuffer 이게 i/o 병목이다. 워커쓰레드가 트랜젝션 로그블럭을 로그버퍼에 쓰려고 하는데 로그버퍼가 없어 대기하는 상황이다.  다른 워커쓰레드가 writelog 가 블럭을 잡고 있기 때문이다. 

Used to indicate a worker thread is waiting for a log buffer to write log blocks for a transaction

This is typically a symptom of I/O bottlenecks because other workers waiting on WRITELOG will hold on to log blocks. Look for WRITERLOG waiters and if found the overall problem is I/O bottleneck on the storage system associated with the transaction log

 

똑똑한 아저씨들 링크

http://blogs.msdn.com/b/psssql/archive/2009/11/03/the-sql-server-wait-type-repository.aspx


다른거 유용한거 있으면 댓글 받아요~ 같이 만들어 보아요~

 

 

Posted by 보미아빠
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함