2012-07-10 17 views
8

Potrzebuję pobrać niektóre dane na podstawie słowa kluczowego, zapytanie jest testowane do 100% dokładne, ale problem polega na tym, że ładowanie reader jest dość powolne. Próbowałem zastąpić to zapytanie tym, który nie zawiera w ogóle inner join s, a ładowanie było dość szybkie. Zastanawiam się, skoro w rezultacie wybieram tylko jedną kolumnę, dlaczego metoda DataTable.Load() zajmuje tyle czasu? Czy to jest SQLite, który ładuje całe wyniki, a nie tylko jedną kolumnę?Ładowanie czytnika danych jest bardzo powolne.

Przed użyciem DataTable średni czas wykonywania każdego z nich wynosił 7 sekund.

To jest mój kod:

_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

Wygląda na to, że zapytanie jest po prostu powolne. Czy jest inny sposób dostępu do twoich stołów, tak że nie musisz robić tak wielu złączeń? – Tejs

+0

Wiedziałem, że to będzie bolało ... Niestety musimy połączyć 2 tabele w oparciu o jedno z pól. Te połączenia są jedynym połączeniem między nimi, biorąc pod uwagę bieżący schemat bazy danych. – iCantSeeSharp

+0

Co to jest "_database" i dlaczego ma takie metody jak 'Connect' i' Disconnect'? Nie wymyślaj ponownie koła. Powinieneś również użyć instrukcji "using-statement" dla swojego połączenia, aby upewnić się, że zostanie "zamknięte" tak szybko, jak to możliwe. Czy jest to środowisko wielowątkowe, takie jak ASP.NET? –

Odpowiedz

2

The SQLite Query Planner oferuje kilka wskazówek dotyczących optymalizacji zapytań dla SQLite.

pewne elementy, które mogą mieć zastosowanie do Twojego pytania:

1.) W związku z wdrożeniem w SQLite możesz spróbować zmienić kolejność wielokrotny dołącza:

Obecna implementacja używa tylko SQLite dołączanie pętli. To znaczy , powiedzmy, że połączenia są realizowane jako pętle zagnieżdżone. Domyślna kolejność zagnieżdżonych pętli w złączeniu jest dla najbardziej lewej tabeli w klauzuli FROM do tworząc pętlę zewnętrzną i najbardziej prawą tabelę w celu utworzenia wewnętrznej pętli.

W zależności od konstrukcji JOIN może występować różnica w wydajności.

SQLite stara się zoptymalizować to automatycznie, ale o ile dobrze zrozumiałem dokumentacji nie ma żadnej gwarancji na sukces (pasemka przeze mnie):

Jednakże SQLite będzie gniazdo pętle w innej kolejności, jeśli robi więc pomoże jej wybrać lepsze wskaźniki. [...] Przyłącz się do zmiany kolejności jest automatyczne i zwykle działa na tyle dobrze, że programiści nie muszą o tym myśleć, szczególnie, jeśli ANALYZE został użyty do zebrania statystyk o dostępnych indeksach . Ale czasami potrzebne są pewne wskazówki od programisty .

2.) Należy również pamiętać, że sprzężenia wewnętrzne są wewnętrznie przekształcony WHERE, więc każdy z porad występ w których mogą mieć zastosowanie sekcja dokumentu, TOO:

ON oraz klauzule USING połączenia wewnętrznego są konwertowane na dodatkowych warunków klauzuli WHERE przed analizą klauzuli WHERE opisaną powyżej w paragrafie 1.0. Tak więc w SQLite nie ma żadnej przewagi obliczeniowej, aby użyć nowszej składni połączenia SQL92 w stosunku do starszej składni SQLA-0189.Obaj kończą się osiągnięciem dokładnie tego samego na wewnętrznych sprzężeniach.

3.) Można rozważyć, aby wybrać więcej kolumn w wyciągu, jeśli istnieją indeksy na nich:

Nie jest konieczne dla każdej kolumny indeksu do stawienia się w WHERE w celu zastosowania tego indeksu. Ale tam nie może być odstępami w kolumnach indeksu, które są używane.

+0

Wszystkie sprzężenia są zbudowane na kluczach podstawowych, myślę, że to rozwiązuje problem związany z indeksowaniem, ale naprawdę próbuję się zastanowić, czy 1 + 2 może być ratunkiem dla mojego przypadku. – iCantSeeSharp

+0

Użyłem 'ANALYZE' przed komendą sql, a zapytanie zostało wykonane dość szybko. Biorąc pod uwagę, że podałeś właściwy kierunek dla tego konkretnego problemu, otrzymujesz odpowiedź. Dzięki! – iCantSeeSharp

3

myślę, że to się stanie należycie charakter SQLite i wielką liczbę łączy.

Spróbuj refaktoryzować schemat bazy danych, np. Denormalizuj dane, aby uzyskać szybszy dostęp.

+0

Czy "charakter SQLite" oznacza, że ​​oczekiwane wyniki różnią się od obecnie zwracanych? – iCantSeeSharp

+0

@Svvlaki: Mam na myśli to, że SQLite nie obsługuje dobrego obciążenia dla takiej liczby sprzężeń, możesz również mieć duży plik, który pogarsza również wynikową trwałość. – abatishchev

+0

Mimo że zapytanie jest dość szybkie na Navicat? – iCantSeeSharp

Powiązane problemy