2012-07-10 9 views
8

Ho bisogno di recuperare alcuni dati in base a una parola chiave, la query è testata al 100% preciso, ma il problema è il caricamento del reader è piuttosto lento. Ho provato a sostituire questa query con una che non contiene inner join s e il caricamento è stato piuttosto veloce. Quindi mi chiedo, dal momento che sto selezionando solo una colonna, perché DataTable.Load() richiede così tanto tempo? È lo di che carica l'intero risultato e non solo l'una colonna?Il caricamento del lettore DataTable è molto lento

Prima di utilizzare il DataTable, il tempo medio di esecuzione di ogni reader.Read() era 7 secondi.

Questo è il mio codice:

_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

Sembra che la query sia semplicemente lenta. C'è un modo diverso di accedere alle tue tabelle in modo tale da non dover fare così tanti join? – Tejs

+0

Sapevo che questo avrebbe fatto male .. Purtroppo abbiamo bisogno di collegare le 2 tabelle in base a uno dei campi. Questi join sono l'unica connessione tra loro, dato lo schema DB attuale. – iCantSeeSharp

+0

Che cos'è '_database' e ​​perché ha metodi come' Connect' e 'Disconnect'? Non reinventare la ruota. Dovresti anche usare un 'using-statement' per la tua connessione per assicurarti che venga" chiuso "il prima possibile. È un ambiente multithreading come ASP.NET? –

risposta

2

The SQLite Query Planner offre alcuni suggerimenti sull'ottimizzazione delle query per SQLite.

Alcuni elementi che possono applicarsi alla tua domanda:

1.) a causa della realizzazione di SQLite si potrebbe provare a ri-ordinare il più join:

L'implementazione corrente di SQLite utilizza solo loop si unisce. Vale a dire , i join vengono implementati come cicli nidificati. L'ordine predefinito dei cicli nidificati in un join è per la tabella più a sinistra nella clausola FROM a forma il ciclo esterno e la tabella all'estrema destra per formare il ciclo interno.

Quindi, a seconda di come vengono costruiti i JOIN, potrebbe esserci una differenza nelle prestazioni.

SQLite cerca di ottimizzare automaticamente, ma per quanto ho capito la documentazione non v'è alcuna garanzia di successo (punti salienti da me):

Tuttavia, SQLite si nidificano i loop in un ordine diverso se facendo quindi ti aiuterà a selezionare indici migliori. [...] Unire il riordino è automatico e in genere funziona abbastanza bene che i programmatori non devono pensarci, specialmente se ANALYZE è stato utilizzato per raccogliere le statistiche sugli indici disponibili. Ma occasionalmente sono necessari alcuni suggerimenti dal programmatore .

2.) Inoltre, si ricorda che inner join vengono convertiti internamente in clausole WHERE, in modo che qualsiasi delle punte prestazioni nel WHERE potrebbe applicare sezione del documento, anche:

L'ON e le clausole USING di un join interno vengono convertite in termini aggiuntivi della clausola WHERE prima dell'analisi della clausola WHERE descritta sopra al paragrafo 1.0. Pertanto, con SQLite, non è disponibile il vantaggio computazionale per utilizzare la più recente sintassi di join SQL92 sulla sintassi virgola mobile SQL89 precedente .Entrambi finiscono per realizzare esattamente lo la stessa cosa sui join interni.

3.) Si potrebbe prendere in considerazione per selezionare più colonne nella vostra dichiarazione, se ci sono indici su di loro:

Non è necessario per ogni colonna di un indice a comparire in un WHERE termine della clausola per l'utilizzo di tale indice. Ma lo non può essere intervalli nelle colonne dell'indice utilizzato.

+0

Tutti i join sono basati su chiavi primarie, penso che questo risolva il problema dell'indicizzazione, ma sto davvero cercando di pensare se 1 + 2 potrebbe essere un risparmiatore di vita per il mio caso. – iCantSeeSharp

+0

Ho usato 'ANALYZE' prima del mio comando sql e la query è stata eseguita abbastanza velocemente. Quindi, considerando che hai fornito la direzione corretta per questo problema specifico, ottieni la risposta. Grazie! – iCantSeeSharp

3

Penso che questo accade a causa di una natura SQLite e gran numero di join.

Provare a eseguire lo schema del database di refactoring, come denormalizzare i dati per un accesso più rapido.

+0

La "natura di SQLite" indica che i risultati previsti sono diversi da quelli attualmente restituiti? – iCantSeeSharp

+0

@Souvlaki: Voglio dire che SQLite non supporta un buon carico per un tale numero di join, inoltre potresti avere un file di grandi dimensioni che degrada anche la permanenza risultante. – abatishchev

+0

Anche se la query è abbastanza veloce su Navicat? – iCantSeeSharp