2012-07-10 6 views
8

키워드를 기반으로 일부 데이터를 가져와야하지만 쿼리가 100 % 정확하게 테스트되었지만 문제는 reader의로드가 매우 느립니다. 나는이 쿼리를 inner join을 포함하지 않는 것으로 바꾸려고 시도했는데 로딩이 꽤 빠르다. 결과적으로 하나의 열만 선택했기 때문에 DataTable.Load()에 왜 많은 시간이 걸리는지 궁금합니다. SQLiteExecuteReader은 하나의 열뿐만 아니라 전체 결과를로드합니까?DataTable 리더로드가 매우 느립니다.

DataTable을 사용하기 전에 각 reader.Read()을 실행하는 평균 시간은 7 초입니다. 나는이 SQLite는의 인해 자연과 조인의 큰 숫자를 어떻게 생각

_database.Connect(); 

var selectCommand = new SQLiteCommand(
@"SELECT A.ID AS MY_ID FROM MD 
INNER JOIN TMD ON MD.ID = TMD.ID_MD 
INNER JOIN TR ON TR.ID = TMD.ID_TR 
INNER JOIN P ON P.ID = TR.ID_P 
INNER JOIN DP ON DP.ID_P = P.ID 
INNER JOIN CD ON CD.ID = DP.ID_CD 
WHERE CD.DESC = @desc" 
); 

selectCommand.Parameters.AddWithValue("@desc", value); 

using (DbDataReader reader = _database.ExecuteQuery(selectCommand)) 
{ 
    DataTable data = new DataTable("MyData"); 
    data.Load(reader); 
} 
_database.Disconnect(); 
+1

검색어가 단순히 느린 것 같습니다. 이렇게 많은 조인을 할 필요가 없도록 테이블에 액세스하는 다른 방법이 있습니까? – Tejs

+0

나는 이것이 상처를받을 것이라는 것을 알고있었습니다. 불행하게도 우리는 필드 중 하나를 기반으로 2 개의 테이블을 연결해야합니다. 이러한 조인은 현재 DB 스키마가 주어지면 이들 간의 유일한 연결입니다. – iCantSeeSharp

+0

'_database' 란 무엇이며 왜 '연결'과 '연결 끊기'와 같은 메소드를 사용합니까? 바퀴를 재발 명하지 마십시오. 가능한 한 빨리 "닫힌다"는 것을 보장하기 위해서 당신의 연결에 대해서'using 문 '을 사용해야한다. ASP.NET과 같은 다중 스레드 환경입니까? –

답변

2

The SQLite Query Planner은 SQLite에 대한 쿼리 최적화에 대한 몇 가지 힌트를 제공합니다.

질문에 적용 할 수있는 일부 항목 :

SQLite는 현재 구현에만 사용하면 여러 조인 순서를 다시 시도 할 수 있습니다 SQLite는의 구현으로 인해

1) 루프 조인. 즉, 으로, 조인은 중첩 루프로 구현됩니다. 조인에서 중첩 된 루프의 기본 순서는 의 FROM 절의 가장 왼쪽 테이블에 대해 외부 루프를 구성하고 가장 오른쪽에있는 테이블을 사용하여 내부 루프를 형성하는 것입니다.

따라서 JOIN이 어떻게 구성되어 있는지에 따라 성능에 차이가있을 수 있습니다.

SQLite는이 작업을 자동으로 최적화하려고하지만, 지금까지의 내가 문서를 이해로 (내게로 하이라이트) 성공을위한 보증은 없다 그러나

, SQLite는 중첩 다른 순서로 루프는 일을한다면 그래서 은 더 나은 지표를 선택하는 데 도움이 될 것입니다. [...] Join reordering은 자동으로 수행되며 일반적으로 프로그래머가 에 대해 생각할 필요가 없습니다. 특히 ANALYZE가 사용 가능한 인덱스에 대한 통계를 수집하는 데 사용 된 경우 적합합니다. 그러나 간혹 프로그래머의 힌트가 필요합니다.

2) 또한, INNER 내부 WHERE 절, 그래서 너무 문서의 섹션이 해당 될 수있는 성능 팁, 어떤으로 변환 조인주의하십시오 :

온 및 내부 조인의 USING 절은 위 단락 1.0에서 설명한 WHERE 절 분석 에 앞서 WHERE 절의 추가 용어 으로 변환됩니다. 따라서 SQLite의 경우 이전 SQL89 쉼표 - 조인 구문보다 최신 SQL92 조인 구문을 사용하는 것이 유리합니다.둘 다 정확하게 내부 조인에 대해 동일한 작업을 수행합니다.

3) 그들에 어떤 인덱스가있는 경우 당신은 당신의 문에 더 열을 선택하는 것이 좋습니다 :

WHERE 에 표시 인덱스의 모든 열 필요하지 않습니다

절을 사용하여 해당 색인을 사용합니다. 그러나 거기에 간격의 색인에서 사용되는 열 수 없습니다.

+0

모든 조인은 기본 키를 기반으로 작성되었으므로 인덱싱에 대한 문제를 해결할 수 있다고 생각하지만 실제로 1 + 2가 내 경우에 생명의 은인이 될 수 있다고 생각하고 있습니다. – iCantSeeSharp

+0

제 SQL 명령 전에'ANALYZE'를 사용했는데 쿼리가 꽤 빠르게 실행되었습니다. 따라서이 특정 문제에 대한 올바른 방향을 제공했다는 것을 고려하면 대답을 얻을 수 있습니다. 감사! – iCantSeeSharp

3

:

이 내 코드입니다.

빠른 액세스를 위해 데이터를 역 정규화하는 것과 같은 데이터베이스 스키마를 리팩토링하십시오.

+0

"자연의 SQLite"는 예상 결과가 현재 반환 된 것과 다른 것을 의미합니까? – iCantSeeSharp

+0

@Souvlaki : SQLite가 그러한 수의 조인에 적합한로드를 지원하지 않는다는 것을 의미합니다. 또한 결과 파일의 영속성을 저하시키는 큰 파일이있을 수 있습니다. – abatishchev

+0

Navicat에서 쿼리가 꽤 빠르지 만? – iCantSeeSharp