Chociaż szanuję zgłaszającego, pokornie nie zgadzam się z udzieloną odpowiedzią, a nie z „powodów religijnych”. Innymi słowy, uważam, że firma Microsoft nie zapewniła żadnego narzędzia, które zmniejszałoby potrzebę korzystania z procedur przechowywanych w wytycznych.
Wszelkie wskazówki udzielane deweloperowi, które faworyzują stosowanie zapytań SQL w postaci nieprzetworzonego tekstu, muszą być wypełnione wieloma zastrzeżeniami, tak więc uważam, że najrozsądniejszą radą jest znaczne zachęcanie do korzystania z procedur przechowywanych i zniechęcanie zespołów programistów do udziału w praktyce osadzania instrukcji SQL w kodzie lub przesyłania surowych, zwykłych tekstowych żądań SQL poza SQL SPROC (procedury składowane).
Myślę, że prosta odpowiedź na pytanie, dlaczego używać SPROC, jest taka, jak zakładał autor: SPROC są analizowane, optymalizowane i kompilowane. W związku z tym ich plany zapytań / wykonania są buforowane, ponieważ zapisano statyczną reprezentację zapytania, a Ty będziesz go różnicować tylko według parametrów, co nie jest prawdą w przypadku skopiowanych / wklejonych instrukcji SQL, które prawdopodobnie zmieniają się od strony do strony i komponentu / warstwy, i często są zmienne w zakresie, w jakim różne tabele, nawet nazwy baz danych, mogą być określane od wezwania do wywołania. Zezwolenie na ten rodzaj dynamicznego ad hocPrzesyłanie kodu SQL znacznie zmniejsza prawdopodobieństwo, że silnik DB ponownie użyje planu zapytań do instrukcji ad hoc, zgodnie z pewnymi bardzo surowymi zasadami. W tym miejscu dokonuję rozróżnienia między dynamicznymi zapytaniami ad hoc (w duchu postawionego pytania) a użyciem wydajnego Systemu SPROC sp_executesql.
Mówiąc dokładniej, istnieją następujące elementy:
- Szeregowe i równoległe plany zapytań, które nie zawierają kontekstu użytkownika i pozwalają na ponowne użycie przez silnik DB.
- Kontekst wykonania, który umożliwia ponowne wykorzystanie planu zapytań przez nowego użytkownika z różnymi parametrami danych.
- Pamięć podręczna procedur, o którą pyta silnik DB w celu uzyskania oczekiwanej wydajności.
Gdy ze strony internetowej wydawana jest instrukcja SQL, zwana „instrukcją ad hoc”, silnik szuka istniejącego planu wykonania, który obsłużyłby żądanie. Ponieważ jest to tekst przesłany przez użytkownika, zostanie przyjęty, przeanalizowany, skompilowany i wykonany, jeśli jest poprawny. W tej chwili otrzyma zerowy koszt zapytania. Koszt zapytania jest wykorzystywany, gdy silnik DB korzysta z algorytmu w celu ustalenia, które plany wykonania zostaną wykluczone z pamięci podręcznej.
Kwerendy ad hoc otrzymują domyślnie zerową wartość kosztu zapytania. Po kolejnym wykonaniu dokładnie tego samego tekstu zapytania ad hoc przez inny proces użytkownika (lub ten sam) bieżący koszt zapytania jest resetowany do pierwotnego kosztu kompilacji. Ponieważ nasz koszt kompilacji zapytań ad hoc wynosi zero, nie wróży to dobrze możliwości ponownego użycia. Oczywiście zero jest najmniej wartościowaną liczbą całkowitą, ale dlaczego miałaby być eksmitowana?
Gdy pojawią się presje pamięciowe, które będą występować, jeśli masz często używaną witrynę, silnik DB korzysta z algorytmu czyszczenia w celu ustalenia, w jaki sposób może odzyskać pamięć używaną przez pamięć podręczną procedury. Wykorzystuje bieżący koszt zapytania, aby zdecydować, które plany eksmisji. Jak można się domyślać, plany z zerowym kosztem są pierwszymi, które są eksmitowane z pamięci podręcznej, ponieważ zero zasadniczo oznacza „brak obecnych użytkowników lub odniesienia do tego planu”.
- Uwaga: Plany wykonania ad hoc - bieżący koszt jest zwiększany o każdy proces użytkownika o pierwotny koszt kompilacji planu. Jednak maksymalny koszt żadnego planu nie może przekraczać pierwotnego kosztu kompilacji ... w przypadku zapytań ad hoc ... zero. Tak więc zostanie „powiększony” o tę wartość… zero - co zasadniczo oznacza, że pozostanie planem o najniższych kosztach.
Dlatego jest całkiem prawdopodobne, że taki plan zostanie najpierw eksmitowany, gdy pojawi się presja pamięci.
Jeśli więc masz serwer z dużą ilością pamięci „przekraczającą Twoje potrzeby”, problem może nie występować tak często, jak zajęty serwer, który ma tylko „wystarczającą” pamięć, aby obsłużyć swoje obciążenie. (Niestety, pojemność pamięci serwera i wykorzystanie są nieco subiektywne / względne, chociaż algorytm nie jest.)
Teraz, jeśli nie mam racji co do jednego lub więcej punktów, z pewnością jestem otwarty na korektę.
Na koniec autor napisał:
„Teraz mamy optymalizację na poziomie instrukcji, więc odpowiednio sparametryzowane zapytanie pochodzące z aplikacji może korzystać z tego samego planu wykonania, co zapytanie wbudowane w procedurę przechowywaną”.
Uważam, że autor odnosi się do opcji „optymalizuj pod kątem obciążeń ad hoc”.
Jeśli tak, ta opcja umożliwia dwuetapowy proces, który pozwala uniknąć natychmiastowego wysłania pełnego planu zapytań do pamięci podręcznej procedury. Wysyła tam tylko mniejszy kod zapytania. Jeśli dokładne wywołanie zapytania zostanie wysłane z powrotem do serwera, gdy kod pośredniczący zapytania nadal znajduje się w pamięci podręcznej procedury, wówczas pełny plan wykonania zapytania zostanie zapisany w pamięci podręcznej procedury. Oszczędza to pamięć, która podczas incydentów związanych z ciśnieniem pamięci może pozwolić algorytmowi eksmisji na eksmisję twojego kodu pośredniczącego rzadziej niż większy buforowany plan zapytań. Znowu zależy to od pamięci serwera i wykorzystania.
Musisz jednak włączyć tę opcję, ponieważ jest ona domyślnie wyłączona.
Na koniec chcę podkreślić, że często powodem, dla którego programiści osadzają SQL na stronach, komponentach i innych miejscach, jest to, że chcą być elastyczni i przesyłać dynamiczne zapytania SQL do silnika bazy danych. Dlatego w rzeczywistym przypadku użycia przesłanie tego samego tekstu, wywołanie połączenia, jest mało prawdopodobne, podobnie jak buforowanie / wydajność, której szukamy, przesyłając zapytania ad hoc do programu SQL Server.
Aby uzyskać dodatkowe informacje, zobacz:
https://technet.microsoft.com/en-us/library/ms181055(v=sql.105).aspx
http://sqlmag.com/database-performance-tuning/don-t-fear-dynamic-sql
Cześć,
Henry