Tworzenie tabeli jest operacją stosunkowo zasobożerną i czasochłonną. Serwer musi zlokalizować i przydzielić przestrzeń pamięci dla nowych struktur danych i indeksów oraz dokonać odpowiednich wpisów w wielu tabelach metadanych systemu. Cała ta praca musi być wykonana w sposób, który zawsze będzie działał poprawnie przy wysokiej współbieżności i który spełnia wszystkie gwarancje ACID oczekiwane od relacyjnej bazy danych.
W SQL Server oznacza to przyjmowanie odpowiednich rodzajów blokad i zatrzasków we właściwej kolejności, przy jednoczesnym zapewnieniu, że szczegółowe wpisy dziennika transakcji są bezpiecznie umieszczane w trwałym magazynie przed jakimikolwiek fizycznymi zmianami w bazie danych. Te wpisy w dzienniku zapewniają, że system może przywrócić bazę danych do spójnego stanu w przypadku cofnięcia transakcji lub awarii systemu.
Upuszczenie stołu to podobnie kosztowna operacja. Na szczęście większość baz danych nie tworzy ani nie usuwa tabel z dużą częstotliwością. Oczywistym wyjątkiem jest systemowa baza danych tempdb . Ta pojedyncza baza danych zawiera fizyczne przechowywanie, struktury alokacji, metadane systemu i wpisy dziennika transakcji dla wszystkich tabel tymczasowych i zmiennych tabel w całej instancji SQL Server.
Jest to natura tabel tymczasowych i zmiennych tabel, które są tworzone i usuwane znacznie częściej niż inne typy obiektów bazy danych. Kiedy ta naturalnie wysoka częstotliwość tworzenia i niszczenia jest połączona z efektem koncentracji wszystkich tabel tymczasowych i zmiennych tabel powiązanych z pojedynczą bazą danych, trudno się dziwić, że rywalizacja może powstać w alokacji i strukturach metadanych tempdb baza danych.
Tymczasowe buforowanie obiektów
Aby zmniejszyć wpływ na tempdb struktury, SQL Server może buforować obiekty tymczasowe do ponownego wykorzystania. Zamiast usuwać obiekt tymczasowy, SQL Server zachowuje metadane systemu i obcina dane tabeli. Jeśli tabela ma rozmiar 8 MB lub mniej, obcinanie jest wykonywane synchronicznie; w przeciwnym razie stosuje się odroczony spadek. W obu przypadkach obcięcie zmniejsza zapotrzebowanie na pamięć do pojedynczej (pustej) strony danych, a informacje o alokacji do pojedynczej strony uprawnień.
Buforowanie pozwala uniknąć prawie wszystkich kosztów alokacji i metadanych związanych z tworzeniem tymczasowego obiektu następnym razem. Jako efekt uboczny wprowadzania mniejszej liczby zmian w tempdb bazy danych niż pełny cykl upuszczania i odtwarzania, tymczasowe buforowanie obiektów również zmniejsza ilość wymaganego rejestrowania transakcji.
Uzyskiwanie buforowania
Zmienne tabel i lokalne tabele tymczasowe mogą być buforowane. Aby kwalifikować się do buforowania, lokalna tabela tymczasowa lub zmienna tabeli musi być utworzone w module:
- Procedura składowana (w tym tymczasowa procedura składowana)
- Wyzwalacz
- Wielozdaniowa funkcja z wartościami tabelarycznymi
- Skalarna funkcja zdefiniowana przez użytkownika
Wartość zwracana przez wieloinstrukcyjną funkcję zwracającą tabelę jest zmienną tabeli, która sama może być buforowana. Parametry wyceniane w tabeli (które są również zmiennymi tabeli) mogą być buforowane, gdy parametr jest wysyłany z aplikacji klienckiej, na przykład w kodzie .NET przy użyciu SqlDbType.Structured
. Gdy instrukcja jest sparametryzowana, struktury parametrów wyceniane w tabeli mogą być buforowane tylko w SQL Server 2012 lub nowszym.
Następujące nie mogą być w pamięci podręcznej:
- Globalne tabele tymczasowe
- Obiekty utworzone przy użyciu ad-hoc SQL
- Obiekty utworzone za pomocą dynamicznego SQL (np. za pomocą
EXECUTE
lubsys.sp_executesql
)
Aby zostać zbuforowanym, tymczasowy obiekt dodatkowo nie może :
- Miej nazwane ograniczenia (ograniczenia bez wyraźnych nazw są w porządku)
- Wykonaj „DDL” po utworzeniu obiektu
- Bądź w module zdefiniowanym za pomocą
WITH RECOMPILE
opcja - Bądź wywoływany za pomocą
WITH RECOMPILE
opcjaEXECUTE
oświadczenie
Aby wyraźnie odnieść się do niektórych typowych nieporozumień:
TRUNCATE TABLE
nie zapobiegaj buforowaniuDROP TABLE
nie zapobiegaj buforowaniuUPDATE STATISTICS
nie zapobiegaj buforowaniu- Automatyczne tworzenie statystyk nie zapobiegaj buforowaniu
- Instrukcja
CREATE STATISTICS
będzie zapobiegaj buforowaniu
Wszystkie tymczasowe obiekty w module są osobno oceniane pod kątem przydatności do buforowania. Moduł zawierający jeden lub więcej obiektów tymczasowych, których nie można buforować, może nadal kwalifikować się do buforowania innych obiektów tymczasowych w tym samym module.
Typowym wzorcem, który wyłącza buforowanie tabel tymczasowych, jest tworzenie indeksów po początkowej instrukcji tworzenia tabeli. W większości przypadków można to obejść za pomocą klucza podstawowego i ograniczeń unikatowości. W SQL Server 2014 i nowszych mamy możliwość dodawania nieunikalnych indeksów nieklastrowanych bezpośrednio w instrukcji tworzenia tabeli przy użyciu INDEX
klauzula.
Monitorowanie i konserwacja
Możemy zobaczyć, ile tymczasowych obiektów jest obecnie buforowanych za pomocą liczników pamięci podręcznej DMV:
SELECT DOMCC.[typ], DOMCC.pages_kb, DOMCC.pages_in_use_kb, DOMCC.entries_count, DOMCC.entries_in_use_countFROM sys.dm_os_memory_cache_counters AS DOMCC WHERE DOMCC.[nazwa] =N' &Tabela zmiennych tymczasowych>Przykładowy wynik to:
Wpis w pamięci podręcznej jest uważany za w użyciu tak długo, jak wykonywana jest dowolna część modułu zawierającego. Równoczesne wykonywanie tego samego modułu spowoduje utworzenie wielu obiektów tymczasowych w pamięci podręcznej. Wiele planów wykonania dla tego samego modułu (być może z powodu różnych sesji
SET
opcje) będą również prowadzić do wielu wpisów w pamięci podręcznej dla tego samego modułu.Wpisy w pamięci podręcznej mogą z czasem ulec przedawnieniu w odpowiedzi na konkurencyjne zapotrzebowanie na pamięć. Buforowane obiekty tymczasowe można również usunąć (asynchronicznie, przez wątek systemowy w tle), gdy plan wykonania modułu nadrzędnego zostanie usunięty z pamięci podręcznej planu.
Chociaż nie jest to obsługiwane (ani w żaden sposób zalecane) dla systemów produkcyjnych, tymczasowy magazyn obiektów w pamięci podręcznej można ręcznie całkowicie wyczyścić w celach testowych za pomocą:
DBCC FREESYSTEMCACHE ('Tymczasowe tabele i zmienne tabel') Z MARK_IN_USE_FOR_REMOVAL; CZEKAJ NA OPÓŹNIENIE '00:00:05';Pięciosekundowe opóźnienie pozwala na uruchomienie zadania czyszczenia w tle. Pamiętaj, że to polecenie jest właściwie niebezpieczne . Powinieneś go używać (na własne ryzyko) tylko na instancji testowej, do której masz wyłączny dostęp. Po zakończeniu testowania uruchom ponownie instancję SQL Server.
Szczegóły implementacji buforowania
Zmienne tabel są implementowane przez „prawdziwą” tabelę użytkownika w tempdb bazy danych (chociaż nie tabeli, do której możemy bezpośrednio zapytać). Nazwa powiązanej tabeli to „#”, po której następuje ośmiocyfrowa szesnastkowa reprezentacja identyfikatora obiektu. Poniższe zapytanie pokazuje relację:
-- Zmienna tabeli DECLARE @Z AS table (z integer NULL); -- Odpowiedni wpis sys.tables SELECT T.[nazwa], ObjIDFromName =CONVERT(integer, CONVERT(binary(4), RIGHT(T.[name], 8), 2)), T.[object_id], T.[ type_desc], T.create_date, T.modify_dateFROM tempdb.sys.tables AS T WHERE T.[nazwa] LIKE N'#[0-9A-F][0-9A-F][0-9A-F][0 -9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]';Przykładowy wynik pokazano poniżej. Zwróć uwagę, że identyfikator obiektu obliczony na podstawie nazwy obiektu pasuje do rzeczywistego identyfikatora obiektu:
Uruchomienie tego skryptu jako ad-hoc SQL spowoduje utworzenie innego tempdb identyfikator obiektu (i nazwa obiektu) przy każdym wykonaniu (bez buforowania). Umieszczenie tego samego skryptu wewnątrz modułu (np. procedury składowanej) umożliwi buforowanie zmiennej tabeli (o ile nie jest używany dynamiczny SQL), dzięki czemu identyfikator i nazwa obiektu będą takie same przy każdym wykonaniu.
Gdy zmienna table nie jest buforowana, tabela bazowa jest tworzona i usuwana za każdym razem. Gdy włączone jest tymczasowe buforowanie obiektów, tabela jest obcinana na końcu modułu, a nie usuwana. Nie ma brak zmian do metadanych systemowych, gdy zmienna tabeli jest buforowana. Wpływ na struktury alokacji i rejestrowanie transakcji ogranicza się do usuwania wierszy w tabeli oraz usuwania nadmiaru danych i stron alokacji po zakończeniu modułu.
Tabele tymczasowe
Gdy zamiast zmiennej tabeli używana jest tabela tymczasowa, podstawowy mechanizm jest zasadniczo taki sam, z kilkoma dodatkowymi krokami zmiany nazwy:Gdy tabela tymczasowa nie jest buforowana , jest widoczny w tempdb ze znaną nazwą podaną przez użytkownika, po której następuje kilka znaków podkreślenia i szesnastkowe przedstawienie identyfikatora obiektu jako końcowy sufiks. Lokalna tabela tymczasowa pozostaje, dopóki nie zostanie jawnie usunięta lub dopóki nie zakończy się zakres, w którym została utworzona. W przypadku SQL ad-hoc oznacza to rozłączenie sesji z serwerem.
Dla tabeli tymczasowej z pamięci podręcznej , przy pierwszym uruchomieniu modułu tworzona jest tabela tymczasowa, tak jak w przypadku przypadku niebuforowanego. Na końcu modułu, zamiast automatycznie usuwać (w miarę, jak kończy się zakres, w którym została utworzona), tabela tymczasowa jest obcinana, a następnie zmieniana do szesnastkowej reprezentacji identyfikatora obiektu (dokładnie jak widać dla zmiennej tabeli). Przy następnym uruchomieniu modułu nazwa tabeli w pamięci podręcznej jest zmieniana z formatu szesnastkowego na nazwę podaną przez użytkownika (plus podkreślenia i identyfikator obiektu szesnastkowego).
Dodatkowe operacje zmiany nazwy na początku i na końcu modułu obejmują niewielką liczbę zmian metadanych systemu . Z tego względu buforowane tabele tymczasowe mogą nadal doświadczać przynajmniej częściowej rywalizacji o metadane przy bardzo wysokich wskaźnikach ponownego wykorzystania. Niemniej jednak wpływ na metadane buforowanej tabeli tymczasowej jest znacznie mniejszy niż w przypadku przypadku niebuforowanego (tworzenie i usuwanie za każdym razem tabeli).
Więcej szczegółów i przykładów działania tymczasowego buforowania obiektów można znaleźć w moim poprzednim artykule.
Statystyki dotyczące buforowanych tabel tymczasowych
Jak wspomniano wcześniej, statystyki mogą być automatycznie tworzone na tabelach tymczasowych bez utraty zalet tymczasowego buforowania obiektów (dla przypomnienia, ręczne tworzenie statystyk będzie wyłącz buforowanie).
Ważnym zastrzeżeniem jest to, że statystyki powiązane z buforowaną tabelą tymczasową nie są resetowane gdy obiekt jest buforowany na końcu modułu lub gdy buforowany obiekt jest pobierany z pamięci podręcznej na początku modułu. W konsekwencji statystyki w buforowanej tabeli tymczasowej mogą pozostać po niepowiązanym wcześniejszym wykonaniu. Innymi słowy, statystyki mogą nie mieć absolutnego związku do bieżącej zawartości tabeli tymczasowej.
Jest to oczywiście niepożądane, biorąc pod uwagę, że głównym powodem preferowania lokalnej tabeli tymczasowej nad zmienną tabeli jest dostępność dokładnych statystyk rozkładu. W ramach łagodzenia, statystyki zostaną automatycznie zaktualizowane, gdy (jeśli) skumulowana liczba zmian w bazowym obiekcie w pamięci podręcznej osiągnie wewnętrzny próg rekompilacji. Trudno to ocenić z góry, ponieważ szczegóły są złożone i nieco sprzeczne z intuicją.
Najbardziej wszechstronnym obejściem, przy jednoczesnym zachowaniu zalet tymczasowego buforowania obiektów, jest:
- Ręcznie
UPDATE STATISTICS
na tymczasowej tabeli w module; i - Dodaj
OPTION (RECOMPILE)
wskazówka do instrukcji odwołujących się do tabeli tymczasowej
Oczywiście wiąże się to z pewnymi kosztami, ale najczęściej jest to akceptowalne. Rzeczywiście, decydując się na użycie lokalnej tabeli tymczasowej w pierwszej kolejności, autor modułu domyślnie mówi, że wybór planu jest prawdopodobnie wrażliwy na zawartość tabeli tymczasowej, więc ponowna kompilacja może mieć sens. Ręczna aktualizacja statystyk zapewnia, że statystyki używane podczas rekompilacji odzwierciedlają bieżącą zawartość tabeli (jak z pewnością byśmy się spodziewali).
Aby uzyskać więcej informacji na temat tego, jak to działa, zobacz mój poprzedni artykuł na ten temat.
Podsumowanie i zalecenia
Tymczasowe buforowanie obiektów w module może znacznie zmniejszyć nacisk na współdzieloną alokację i struktury metadanych w tempdb Baza danych. Największa redukcja nastąpi w przypadku korzystania ze zmiennych tabeli, ponieważ buforowanie i ponowne używanie tych obiektów tymczasowych w ogóle nie wiąże się z modyfikowaniem metadanych (bez operacji zmiany nazwy). Spór o struktury alokacji może być nadal widoczny, jeśli pojedyncza strona danych w pamięci podręcznej jest niewystarczająca do przechowywania wszystkich danych zmiennej tabeli w czasie wykonywania.
Wpływ na jakość planu ze względu na brak informacji o liczności dla zmiennych tabeli można złagodzić za pomocą OPTION(RECOMPILE)
lub flaga śledzenia 2453 (dostępna od programu SQL Server 2012 i nowszych). Zwróć uwagę, że te ograniczenia dają optymalizatorowi tylko informacje o całkowitej liczbie wierszy w tabeli.
Aby uogólnić, zmienne tabeli najlepiej stosować, gdy dane są małe (idealnie mieszczą się w obrębie jednej strony danych, aby uzyskać maksymalne korzyści w rywalizacji) i gdy wybór planu nie zależy od wartości obecnych w zmiennej tabeli.
Jeśli informacje o dystrybucji danych (gęstość i histogramy) są ważne przy wyborze planu, użyj lokalnej tabeli tymczasowej zamiast. Upewnij się, że spełniasz warunki tymczasowego buforowania tabeli, co najczęściej oznacza nietworzenie indeksów lub statystyk po początkowej instrukcji tworzenia tabeli. Jest to wygodniejsze od SQL Server 2014 i nowsze dzięki wprowadzeniu INDEX
klauzula CREATE TABLE
oświadczenie.
Wyraźne UPDATE STATISTICS
po załadowaniu danych do tabeli tymczasowej i OPTION (RECOMPILE)
wskazówki dotyczące instrukcji odwołujących się do tabeli mogą być potrzebne do uzyskania wszystkich oczekiwanych korzyści z buforowanych tabel tymczasowych w module.
Ważne jest, aby używać obiektów tymczasowych tylko wtedy, gdy przynoszą wyraźną korzyść, najczęściej pod względem jakości planu. Nadmierne, nieefektywne lub niepotrzebne użycie obiektów tymczasowych może prowadzić do tempdb rywalizacja, nawet po osiągnięciu tymczasowego buforowania obiektów.
Optymalne tymczasowe buforowanie obiektów może nie wystarczyć do zmniejszenia tempdb twierdzenie do akceptowalnych poziomów we wszystkich przypadkach, nawet gdy obiekty tymczasowe są używane tylko wtedy, gdy są w pełni uzasadnione. Używanie zmiennych tabel w pamięci lub nietrwałych tabel w pamięci może zapewnić ukierunkowane rozwiązania w takich przypadkach, chociaż zawsze należy dokonać kompromisów, a żadne pojedyncze rozwiązanie nie stanowi obecnie najlepszej opcji we wszystkich przypadkach.