2016-02-02 62 views
7

Sto usando .NET framework 4.5.1 Linq to SQL.Query singola più lenta di 3 query

ho questa classe di prodotti utilizzando il codice prima:

public class Part 
{ 
    public int PartID { get; set; } 

    [Required(ErrorMessage = "xxx")]   
    public string Title { get; set; } 

    [MaxLength(50)] 
    [Index(IsClustered = false, IsUnique = false,Order =1)] 
    public string Part_Number { get; set; } 

    [MaxLength(50)] 
    [Index(IsClustered = false, IsUnique = false, Order = 2)] 
    public string Manufacturer_Number { get; set; } 
} 

ho circa 2,5 milioni di queste entità nel database.

Primo approccio

var query = db.Parts.Where(s => s.Manufacturer_Number == sstring).ToList();     
query.AddRange(db.Parts.Where(s => s.Part_Number == sstring).ToList()); 
query.AddRange(db.Parts.Where(s => s.Title == sstring).ToList()); 

Secondo approccio

var query = db.Parts.Where(s => s.Manufacturer_Number == sstring 
|| s.Part_Number == sstring || s.Title == sstring).ToList(); 

Il primo approccio è 100 volte più veloce rispetto al secondo approccio. Qualcuno può spiegarlo?

+8

Si dovrebbe guardare SQL che viene prodotto dal proprio linq e quindi controllare il piano di esecuzione in ManagmentStudio. Potrebbe essere che tu abbia indici su ogni campo e le query semplici possono usarli ma non il tuo ultimo. –

+1

Spero che abbia indici se hai 2.5 milioni di record in una tabella ... –

+0

Cosa vuoi esattamente raggiungere ..? –

risposta

1

In primo luogo senza un indice sul titolo, trovo un po 'difficile credere che stai ricevendo il comportamento che rivendichi.

Impostare le statistiche su on almeno e aggiungere i risultati a questa domanda.

Ma detto questo, il primo approccio è in realtà tre viaggi nel database, ma verrà sfruttato l'indexe creato.

Il secondo approccio è un singolo viaggio nel database, ma sicuramente si tradurrà in una scansione completa della tabella, con 2.500.000 di file che probabilmente impiegheranno una quantità non trascurabile di tempo.

+1

Se tutti i campi sono indicizzati, ciò non comporterà una scansione della tabella. L'unico caso a cui posso pensare dove * potrebbe * essere una vera differenza (ovvero l'OP non ha commesso un errore di temporizzazione), è se 'sstring' è NULL.Il titolo ha l'attributo 'Required', che significa NON è NULL. –

+0

@PanagiotisKanavos Sei sicuro che SQL Server utilizzerà più indici in una singola query? –

+0

SQL Server utilizzerà l'opzione più efficiente. Certo che lo sarà, se questa * è * l'opzione più economica. Oppure può decidere di memorizzare i risultati temporanei in tempdb. Statistiche errate o indici mancanti però significa che potrebbe scegliere il piano sbagliato perché non sapeva quale tipo di dati avrebbe trovato in 'Titolo'. In ogni caso, i due approcci non sono nemmeno equivalenti: il primo approccio * restituirà più volte righe che soddisfano più di una condizione. Il secondo approccio filtra le righe in base a tutte le condizioni e le restituisce una volta –

1

come dico problema potrebbe essere in indici se si desidera che la query più veloce con questa query esatto vi suggerisco di creare questo indice:

CREATE NONCLUSTERED INDEX PartIndex 
ON Part (PartID, Manufacturer_Number, Part_Number, Title) 

Non dimenticare di aggiornare le statistiche se si cambia il vostro tavolo dati molto

+2

Numero parte e Numero_prodotto sono già indicizzati. Le proprietà hanno l'attributo 'Index'. È la proprietà 'Title' che non ha un indice. Ci si aspetterebbe che entrambi i tentativi prendessero all'incirca lo stesso tempo a causa di ciò. L'OP deve pubblicare le query generate –

+0

@PanagiotisKanavos d'accordo, aspettiamolo lui –

+0

In tutta semplicità, SQL Server tiene traccia di quali indici * non * hanno e che avrebbero fatto la differenza. Ecco alcuni script che ti diranno quali indici puoi aggiungere, il che darà i migliori miglioramenti nelle prestazioni: http://mikesknowledgebase.com/pages/SQLServer/FindingMissingIndexes.htm –

Problemi correlati