2013-08-29 3 views
2

약 2.500.000 개의 레코드가있는 테이블이있는 데이터베이스가 있습니다. 테스트 할 쿼리가 두 개인 150.000 개의 레코드를 가져옵니다. 첫 번째 결과는 30 초에서 1 분 사이의 결과를 반환합니다. 그러나 두 번째 것은 3-4 분 사이에 반응합니다. 매우 이상합니다. 유일한 변경 사항은 첫 번째 매개 변수는 사용하지 않지만 두 번째 매개 변수는 사용합니다. 나는 C# 둘 다에서 달리고있다. 매개 변수가있는 보안 문제에 대해서는 왜 그렇게 많은 시간이 걸리는지 이해할 수 없습니다. 어떤 도움을 주시면 감사하겠습니다.MSSQL 매개 변수가 더 많은 시간을 소모합니다.

첫 번째 쿼리 :

 DECLARE @page INT=3 
     DECLARE @pagesize INT=300 
      string sql = "SELECT Col1,Col2,Col3 FROM 
    (SELECT ROW_NUMBER() OVER(ORDER BY Col1) AS rownumber,Col1,Col2,Col3"; 
      sql += " FROM my_table WHERE Col1 LIKE '" + letter + "%') as somex 
WHERE rownumber >= (@page-1)*(@pagesize)"; 
      sql += "AND rownumber <=(@page)*@pagesize; 
SELECT COUNT(*) FROM my_table WHERE col1 LIKE '" + letter + "%'"; 

두 번째 쿼리

DECLARE @page INT=3 
    DECLARE @pagesize INT=300 
    DECLARE @starting VARCHAR(10)='be' 
     string sql = "SELECT Col1,Col2,Col3FROM 
(SELECT ROW_NUMBER() OVER(ORDER BY Col1) AS rownumber,Col1,Col2,Col3"; 
     sql += " FROM my_table WHERE Col1 LIKE @letter+'%') as somex 
WHERE rownumber >= (@page-1)*(@pagesize)"; 
     sql += "AND rownumber <=(@page)*@pagesize; SELECT COUNT(*) 
FROM my_table WHERE col1 LIKE @letter+'%'"; 

내 서버가 16기가바이트 램, 4 진짜 4 개의 가상 CPU, SATA 디스크입니다.

편집 : Col1은 클러스터형 및 비 클러스터형 인덱스입니다.

진행률 :이 쿼리는 다른 서버에서 잘 작동하는 것으로 나타났습니다. 그러나 이것은 나를 혼란스럽게합니다. 그것은 SQL Server의 일부 설정 일 수 있습니까?

+4

(소리 https://www.simple-talk.com/sql/t-sql-programming/parameter-sniffing /). – GarethD

+0

GarethD 's 외에도 다음을 수행해야합니다. 1 col1에 인덱스가 있는지 확인하십시오. 2 count (*) 대신 count (col1)를 수행하십시오. 3- 테이블 통계를 업데이트하십시오. – jbl

+0

질문을 편집했습니다. col1에는 클러스터형 및 비 클러스터형 인덱스가 모두 있습니다. count (*)를 count (col1)로 변경했지만 전혀 영향을주지 않았습니다. – Kuzgun

답변

2

내가 코멘트에서 말했듯이, 그것은 parameter sniffing처럼 들리지만, 도움이 될 것이라는 점에서 나는 그것을 확장 할 것이라고 생각했다. 은 내가 원하는 것보다 더 많은 세부 사항을 다루는 웹 기사가 있지만, 스니핑 매개 변수가 길거나 짧으면 SQL Server가 매개 변수 값을 기반으로 실행 계획을 캐시에 저장한다는 것입니다. 현재 값에 대해 최상의 실행 계획을 산출합니다. Col1가 클러스터되지 않은 인덱스가 있지만 비 키 열 등 col2 또는 col3를 포함하지 않는 것으로 가정하면

다음 SQL-서버가 두 가지 옵션, 그 중 하나를 수행 할 수 있습니다 모든 행을 얻을 수 My_Table에 클러스터 된 인덱스 스캔을 할 경우 Col1 LIKE @letter+'%' 또는 Col1에서 색인을 검색 한 다음 클러스터 된 색인에서 책갈피 조회를 수행하여 색인에서 반환 된 각 행에 대해 값을 얻을 수 있습니다. 예상되는 행 수를 기반으로 SQL Server가 두 지점 사이를 전환하는 시점에서 내 머리 꼭대기를 기억할 수는 없습니다. 따라서 백분율이 매우 낮습니다. 따라서 150,000 개의 레코드를 반환하는 경우에는 2,500,000 개 중 클러스터 된 인덱스 스캔을 위해 옵티마이 저는 갈 것입니다. 그러나 몇 백 줄만 돌려 주면 북마크 조회가 바람직합니다.

매개 변수를 사용하지 않으면 SQL Server는 실행될 때마다 새 실행 계획을 만들고 해당 매개 변수에 대한 최상의 실행 계획을 만듭니다 (통계가 최신이라고 가정 할 때). 매개 변수가 처음 실행될 때 매개 변수 매개 변수 값을 기반으로 계획을 생성하고 나중에 사용할 수 있도록 해당 계획을 저장합니다. 쿼리가 계속 실행될 때마다 sql-server는 쿼리가 동일하므로 쿼리를 다시 컴파일하지 않습니다. 즉, 처음 쿼리를 실행 한 경우 에 대해 로우 수가 반환 된 매개 변수가있는 경우 북마크 조회 계획이 저장됩니다. 그런 다음 쿼리가 실행될 때 최적의 계획이 클러스터 된 인덱스 스캔 인 높은 수의 행을 반환하는 값이 전달되면 부 최적의 책갈피 조회를 사용하여 쿼리가 여전히 실행되고 은 실행 시간이 길어집니다 시각. 이것은 물론 다른 방향으로 진실 일 수 있습니다.매개 변수 스니핑을 처리하는 방법은 여러 가지가 있지만 쿼리가 복잡하지 않으므로 컴파일 시간이 중요하지 않습니다. 특히이 쿼리가 을 실행하는 데 30 초를 사용하는 것과 비교할 때 매우 좋습니다. 내가 사용하는 것이 OPTION RECOMPILEQuery hint :

SELECT Col1, Col2, Col3 
FROM ( SELECT ROW_NUMBER() OVER(ORDER BY Col1) AS rownumber,Col1,Col2,Col3 
      FROM my_table 
      WHERE Col1 LIKE @letter+'%' 
     ) as somex 
WHERE rownumber >= (@page-1)*(@pagesize) 
AND  rownumber <= (@page) * @pagesize 
OPTION (RECOMPILE); 

SELECT COUNT(*) 
FROM my_table 
WHERE Col1 LIKE @letter+'%' 
OPTION (RECOMPILE); 

이유 당신이이 매개 변수화 쿼리했다가 새 서버에서 실행 된 처음 컴파일 할 것을 잘 실행되는 새 서버에이 시도 때, 그리고 생성 된 계획은 제공된 매개 변수의 가치에 적합했습니다.

당신이해야 할 다음 OFFSET/FETCH를 사용할 수 페이징을 SQL_Server 2012을 사용하는 경우 마지막 요점 : [매개 변수 스니핑]처럼

SELECT Col1, Col2, Col3 
FROM My_table 
WHERE Col1 LIKE @letter+'%' 
ORDER BY Col1 OFFSET (@page-1) * (@pagesize) ROWS FETCH NEXT @pagesize ROWS ONLY; 
+0

설명 해 주셔서 감사 드리며 시간을내어 주셔서 감사합니다 :) 그러나 문제는 인덱스가 아닙니다. 문제는 C#에서 sql 명령에서 매개 변수를 직접 선언 할 때 command.AddWithValue (...)와 함께 매개 변수를 추가 할 때보 다 빨리 작동합니다. – Kuzgun

+0

오해했습니다. 문제가 있다고 말하지 않았습니다. 색인. 캐시 된 실행 계획을 다시 사용하는 SQL-Server 매개 변수를 사용할 때이 매개 변수는 전달할 매개 변수의 실제 값에 대한 최상의 실행 계획이 아닐 수 있습니다. 이 매개 변수를 사용하지 않으면 SQL Server는 매번 새로운 쿼리이기 때문에 캐시 된 계획을 사용할 수 없습니다. 이것이 차이점을 보여주는 이유입니다. – GarethD

+0

있음 [다른 대답] (http://stackoverflow.com/a/14469603/1048425) 나는 당신이 테스트 할 수 있으며 동일한 쿼리에 대한 작업에서 다른 실행 계획을 볼 수있는 예제 쿼리를 게시했습니다 매개 변수 스니핑에 해냈다. 저장 프로 시저를 사용하지 않더라도 동일한 원칙이 적용됩니다. C#에서 쿼리를 호출한다는 사실은 부적합합니다. – GarethD

관련 문제