In primo luogo ho provato ARITHABORT OFF
su SSMS è ancora meno di 1 secondo.Ef Le interrogazioni Linq sono scadute, ma le stesse query meno di 1 secondo su SSMS
Io uso EntityFramework: 6.1.3 e SQL Azure S1 tier (cercherò con Tier 3 e ti faccio sapere se qualcosa cambia.)
Io uso EF Profiler per ottenere SQL generato da LINQ. Ho interrogato tutti i linq che ho condiviso, sono tutti meno di 1 secondo su SSMS.
Ho 3 milioni di registrazioni sulla tabella AuditLog. Un cliente con ID 3 ha 170 K registra che l'altro cliente con ID 35 ha 125 record. Minimizzerò il codice.
AuditLog Modello:
public class AuditLog
{
public long? CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual CustomerSummary Customer { get; set; }
[Required]
[Index]
public DateTime CreatedDate { get; set; }
}
prima query:
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
se provo con il cliente che ha 170k righe, si dà il tempo fuori eccezione. Se provo con il cliente che ha 125 record, va bene.
Seconda query: È lo stesso con il primo che includo solo i clienti.
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
Il risultato è opposto alla prima query. se provo con il cliente che ha 170k righe, va bene. Se provo con un cliente che ha 125 record, emette un'eccezione di timeout.
Terza query: È lo stesso con la prima query, ma corrisponde a long?
su dove per customerId.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
Il risultato è opposto alla prima query. se provo con il cliente che ha 170k righe, va bene. Se provo con un cliente che ha 125 record, emette un'eccezione di timeout.
Quarta domanda: È lo stesso con la seconda query, ma corrisponde a long?
su dove per customerId.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
Il risultato è l'opposto della seconda query. se provo con il cliente che ha 170k righe, dà un'eccezione time-out. Se provo con il cliente che ha 125 record, va bene.
Sono davvero confuso. Perché l'inner join o la modifica del parametro match a long?
stanno cambiando i risultati? E perché tutte queste query vengono eseguite in meno di 1 secondo su SSMS e danno errori su ef linq?
Errore:
{System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
Aggiornamento (19/04/2016):
Dopo Ivan Stoev suggerimento su commenti.
Have you tried (just for the sake of test) using hardcoded 3 and 35 instead of
customerId
variable?
Non ho ricevuto alcun errore e le query sono più veloci come su SSMS.
Aggiornamento (20/04/2016): Il vero problema è sniffing dei parametri. Quando ho incluso o modificato il parametro in nullable, in realtà ho creato altre query e altri piani di query. Ho creato alcuni piani con il cliente che ha 125 record e gli altri con il cliente che ha 170k record di queste 4 query. Ecco perché ho avuto risultati diversi.
Come stai confrontando i risultati? Stai confrontando l'SQL generato da EF o stai scrivendo il tuo? –
Sql generato da EF. –
Questo è interessante. Potrebbe essere utile anche fornire la versione di EF che stai utilizzando. –