Entity Framework query wolne, ale ten sam SQL w SqlQuery jest szybki
Widzę naprawdę dziwny perf związany z bardzo prostym zapytaniem przy użyciu kodu encji Framework-najpierw z. NET Framework w wersji 4. Zapytanie LINQ2Entities wygląda tak:
context.MyTables.Where(m => m.SomeStringProp == stringVar);
Wykonanie tego zadania zajmuje ponad 3000 milisekund. Wygenerowany SQL wygląda bardzo prosto:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
...
FROM [MyTable] as [Extent1]
WHERE [Extent1].[SomeStringProp] = '1234567890'
To zapytanie uruchamia się niemal natychmiast po uruchomieniu przez Management Studio. Kiedy zmieniam kod C# na funkcję SqlQuery, działa on w ciągu 5-10 milisekund:
context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);
Więc dokładnie to samo SQL, wynikowe encje są śledzone w obu przypadkach, ale wild perf różnica między nimi. Co jest?
7 answers
Znalazłem. Okazuje się, że jest to kwestia typów danych SQL. Kolumna SomeStringProp
w bazie danych była varcharem, ale EF zakłada, że typy łańcuchowe. NET są nvarcharami. Wynikowy proces tłumaczenia podczas zapytania o DB, aby zrobić porównanie, zajmuje dużo czasu. Myślę, że EF Prof prowadził mnie trochę na manowce tutaj, dokładniejsze przedstawienie uruchamianego zapytania byłoby następujące:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
...
FROM [MyTable] as [Extent1]
WHERE [Extent1].[SomeStringProp] = N'1234567890'
Więc wynikową poprawką jest adnotacja modelu code-first, wskazująca na poprawny typ danych SQL:
public class MyTable
{
...
[Column(TypeName="varchar")]
public string SomeStringProp { get; set; }
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-02 19:39:05
Powodem spowolnienia moich zapytań wykonanych w EF było porównanie skalarów nie nullable z skalarami nullable:
long? userId = 10; // nullable scalar
db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value
^^^^^^^^^ ^^^^^^
Type: long Type: long?
To zapytanie zajęło 35 sekund. Ale taki malutki refaktoring:
long? userId = 10;
long userIdValue = userId.Value; // I've done that only for the presentation pursposes
db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
^^^^^^^^^ ^^^^^^^^^^^
Type: long Type: long
Daje niesamowite rezultaty. Ukończenie zajęło tylko 50ms. Możliwe, że jest to błąd w EF.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 10:47:01
Jeśli używasz płynnego mapowania, możesz użyć IsUnicode(false)
jako części konfiguracji, aby uzyskać ten sam efekt -
Http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9
Http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-25 20:36:01
Miałem ten sam problem (zapytanie jest szybkie przy wykonaniu z SQL managera) ale przy wykonaniu z EF upływa limit czasu.
Okazuje się, że encja (która została utworzona z widoku) miała błędne klucze encji. Tak więc encja miała zduplikowane wiersze z tymi samymi kluczami i myślę, że musiała grupować w tle.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-12 18:01:28
Natknąłem się również na to z złożonym zapytaniem ef. Jedną poprawką dla mnie, która zmniejszyła 6-sekundowe zapytanie ef do generowanego sub-sekundowego zapytania sql, było wyłączenie leniwego ładowania.
Aby znaleźć to ustawienie (ef 6) przejdź do.plik edmx i poszukaj w Properties - > Code generation - > lazy Loading Enabled. Ustawione na false.
Ogromna poprawa wydajności jak dla mnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-30 11:40:14
Możesz użyć następujących sztuczek, aby zamocować swoje zapytania -
- Ustaw
ctx.Configuration.ProxyCreationEnabled
Nafalse
tuż przed uzyskaniem kontekstu. - również,
.Select(c => new {c.someproperty})
pobierze tylko wymagane dane, a nie całą masę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-16 20:30:43
Ja też miałem ten problem. Okazuje się, że winowajcą w moim przypadku był sniffing parametru SQL-Server .
Pierwszą wskazówką, że mój problem był w rzeczywistości spowodowany sniffingiem parametrów, było to, że uruchomienie zapytania z "set arithabort off" lub "set arithabort on" dało drastycznie różne czasy wykonania w Management Studio. Dzieje się tak dlatego, że ADO.NET domyślnie używa "set arithabort off", a Management Studio domyślnie "set arithabort on". Pamięć podręczna planu zapytań zachowuje różne plany w zależności od tego parametru.
Wyłączyłem buforowanie planu zapytań dla zapytania, z rozwiązaniem można znaleźć tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 10:35:09