Ten post będzie o tym jak można zrobić sobie krzywdę stosując skądinąd bardzo fajne narzędzia. W tym przypadku mam na myśli CTE (ang. Common Table Expressions). Moim zdaniem stosowane z umiarem podnoszą czytelność kodu, z drugiej jednak strony użycie CTE może wpłynąć negatywnie na wydajność naszych zapytań.
Należy pamiętać o tym, że CTE nie mają fizycznej reprezentacji w tempdb tak jak tabele tymczasowe czy zmienne tabelaryczne. Na CTE można patrzeć jak na taki tymczasowy, nie zmaterializowany widok. Kiedy MSSQL wykonuje zapytanie i napotka CTE to odwołanie do tego CTE zastępuję jego definicją. W związku z tym jeśli dane CTE jest używane kilkakrotnie w danym zapytaniu to ten sam kod zostanie wykonany kilka razy i MSSQL tego nie optymalizuje. Ten kod pokazuje to zachowanie:
Na ekran zostaną wypisane 2 różne identyfikatory. Gdyby Test było tabelą otrzymalibyśmy ten sam wynik. W skrajnych przypadkach może to spowodować, że zapytanie będzie koszmarnie wolne. Optymalizacja jest natomiast prosta. Wystarczy w pewnym momencie wrzucić dane do tabeli tymczasowej i dalej używać tej tabeli zamiast odwoływać się do CTE.
Jakiś czas temu widziałem przypadek gdzie dzięki temu jakże prostemu zabiegowi zapytanie zamiast wykonywać się kilka minut wykonywało się kilka sekund!
Należy pamiętać o tym, że CTE nie mają fizycznej reprezentacji w tempdb tak jak tabele tymczasowe czy zmienne tabelaryczne. Na CTE można patrzeć jak na taki tymczasowy, nie zmaterializowany widok. Kiedy MSSQL wykonuje zapytanie i napotka CTE to odwołanie do tego CTE zastępuję jego definicją. W związku z tym jeśli dane CTE jest używane kilkakrotnie w danym zapytaniu to ten sam kod zostanie wykonany kilka razy i MSSQL tego nie optymalizuje. Ten kod pokazuje to zachowanie:
WITH Test (Id) AS (SELECT NEWID()) SELECT * FROM Test UNION ALL SELECT * FROM Test
Na ekran zostaną wypisane 2 różne identyfikatory. Gdyby Test było tabelą otrzymalibyśmy ten sam wynik. W skrajnych przypadkach może to spowodować, że zapytanie będzie koszmarnie wolne. Optymalizacja jest natomiast prosta. Wystarczy w pewnym momencie wrzucić dane do tabeli tymczasowej i dalej używać tej tabeli zamiast odwoływać się do CTE.
Jakiś czas temu widziałem przypadek gdzie dzięki temu jakże prostemu zabiegowi zapytanie zamiast wykonywać się kilka minut wykonywało się kilka sekund!
Fakt. CTE potrafi trochę namieszać. Przy bardzo dużych zbiorach danych niepotrzebnie zapycha pamięć.
ReplyDelete