Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Jeśli używasz tabel tymczasowych, zmiennych tabeli lub parametrów z wartościami tabeli, rozważ ich konwersje, aby użyć tabel zoptymalizowanych pod kątem pamięci i zmiennych tabeli w celu zwiększenia wydajności. Zmiany kodu są zwykle minimalne.
W tym artykule opisano:
- Scenariusze, które przemawiają za konwersją na przetwarzanie w pamięci.
- Działania techniczne dotyczące wdrażania konwersji do pamięci operacyjnej.
- Wymagania wstępne przed konwersją na w pamięci.
- Przykładowy kod, który wyróżnia zalety wydajności optymalizacji pamięci
Odp. Podstawy zmiennych tabeli zoptymalizowanych pod kątem pamięci
Zmienna tabeli zoptymalizowana pod kątem pamięci zapewnia doskonałą wydajność przy użyciu tego samego algorytmu zoptymalizowanego pod kątem pamięci i struktur danych, które są używane przez tabele zoptymalizowane pod kątem pamięci. Wydajność jest zmaksymalizowana, gdy zmienna tabeli jest uzyskiwana z poziomu natywnie skompilowanego modułu.
Zmienna tabeli zoptymalizowana pod kątem pamięci:
- Jest przechowywany tylko w pamięci i nie ma składnika na dysku.
- Nie obejmuje żadnych działań we/wy.
- Nie obejmuje
tempdb
użycia ani rywalizacji. - Można przekazać do procedury składowanej jako parametr o typie tabelarycznym (TVP).
- Musi mieć co najmniej jeden indeks, skrót lub nieklastrowany.
- W przypadku indeksu skrótu liczba wiaderek powinna optymalnie być 1–2 razy większa od liczby oczekiwanych unikatowych kluczy indeksu, ale przeszacowanie liczby wiaderek jest zazwyczaj akceptowalne (do 10X). Aby uzyskać więcej informacji, zobacz Indeksy dotyczące tabel Memory-Optimized.
Typy obiektów
In-Memory OLTP udostępnia następujące obiekty, których można użyć do optymalizacji pamięci tabel tymczasowych i zmiennych tabeli:
- Tabele zoptymalizowane pod kątem pamięci
- Trwałość = SCHEMA_ONLY
- Zmienne tabeli zoptymalizowane pod kątem pamięci
- Należy zadeklarować w dwóch krokach (zamiast wbudowanych):
-
CREATE TYPE my_type AS TABLE ...;
wtedy -
DECLARE @mytablevariable my_type;
.
-
- Należy zadeklarować w dwóch krokach (zamiast wbudowanych):
B. Scenariusz: zamiana globalnej tabeli tymczasowej
Zastąpienie globalnej tabeli tymczasowej tabelą zoptymalizowaną pod kątem pamięci, typu SCHEMA_ONLY, jest dość proste. Największą zmianą jest utworzenie tabeli w czasie wdrażania, a nie w czasie wykonywania. Tworzenie tabel zoptymalizowanych pod kątem pamięci trwa dłużej niż tworzenie tradycyjnych tabel ze względu na optymalizacje czasu kompilacji. Tworzenie i usuwanie tabel zoptymalizowanych pod kątem pamięci jako część obciążenia operacyjnego online może wpływać na wydajność tego obciążenia, jak również na wydajność operacji redo w drugorzędnych replikach Grupy dostępności Always On i podczas odzyskiwania bazy danych.
Załóżmy, że masz następującą globalną tabelę tymczasową.
CREATE TABLE ##tempGlobalB
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000)
);
Rozważ zastąpienie globalnej tabeli tymczasowej następującą tabelą zoptymalizowaną pod kątem pamięci, która ma trwałość = SCHEMA_ONLY.
CREATE TABLE dbo.soGlobalB
(
Column1 INT NOT NULL INDEX ix1 NONCLUSTERED,
Column2 NVARCHAR (4000)
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);
Kroki
Konwersja z globalnego tymczasowego na SCHEMA_ONLY jest następująca:
- Utwórz tabelę
dbo.soGlobalB
jednorazowo tak samo jak w przypadku dowolnej tradycyjnej tabeli na dysku. - Usuń tworzenie tabeli
##tempGlobalB
z poziomu Transact-SQL (T-SQL). Ważne jest, aby utworzyć tabelę zoptymalizowaną pod kątem pamięci w czasie wdrażania, a nie w czasie wykonywania, aby uniknąć obciążenia kompilacyjnego związanego z tworzeniem tabeli. - W swoim T-SQL zastąp wszystkie wzmianki o
##tempGlobalB
nadbo.soGlobalB
.
C. Scenariusz: Zastępowanie tabeli tymczasowej sesji
Przygotowania do zastąpienia tabeli tymczasowej sesji wymagają użycia większej ilości kodu T-SQL niż w przypadku wcześniejszego scenariusza z tabelą globalną tymczasową. Na szczęście dodatkowy kod T-SQL nie oznacza, że do przeprowadzenia konwersji jest potrzebny żaden większy nakład pracy.
Podobnie jak w przypadku scenariusza globalnej tabeli tymczasowej, największą zmianą jest utworzenie tabeli w czasie wdrażania, a nie w czasie wykonania, aby uniknąć nakładu związanego z kompilacją.
Załóżmy, że masz następującą tabelę tymczasową sesji.
CREATE TABLE #tempSessionC
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000)
);
Najpierw utwórz następującą funkcję tabelaryczną, aby filtrować na @@spid
. Funkcja jest dostępna dla wszystkich tabel SCHEMA_ONLY, które przekonwertujesz z tabel tymczasowych sesji.
CREATE FUNCTION dbo.fn_SpidFilter
(@SpidFilter SMALLINT)
RETURNS TABLE
WITH SCHEMABINDING, NATIVE_COMPILATION
AS
RETURN
SELECT 1 AS fn_SpidFilter
WHERE @SpidFilter = @@spid
Następnie utwórz tabelę SCHEMA_ONLY oraz zasady zabezpieczeń w tabeli.
Każda tabela zoptymalizowana pod kątem pamięci musi mieć co najmniej jeden indeks.
- W przypadku tabeli dbo.soSessionC indeks HASH może być lepszy, jeśli obliczymy odpowiednie BUCKET_COUNT. Jednak w tym przykładzie uprościmy do indeksu typu NONCLUSTERED.
CREATE TABLE dbo.soSessionC
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000) NULL,
SpidFilter SMALLINT DEFAULT (@@spid) NOT NULL,
CONSTRAINT CHK_soSessionC_SpidFilter CHECK (SpidFilter = @@spid),
INDEX ix_SpidFiler NONCLUSTERED (SpidFilter)
-- INDEX ix_SpidFilter HASH
-- (SpidFilter) WITH (BUCKET_COUNT = 64),
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);
GO
CREATE SECURITY POLICY dbo.soSessionC_SpidFilter_Policy
ADD FILTER PREDICATE dbo.fn_SpidFilter(SpidFilter) ON dbo.soSessionC
WITH (STATE = ON);
GO
Po trzecie, w ogólnym kodzie T-SQL:
- Zmień wszystkie odwołania do tabeli tymczasowej w instrukcjach Transact-SQL na nową tabelę zoptymalizowaną pod kątem pamięci:
-
Stary:
#tempSessionC
-
nowy:
dbo.soSessionC
-
Stary:
- Zastąp instrukcje
CREATE TABLE #tempSessionC
w swoim kodzie instrukcjamiDELETE FROM dbo.soSessionC
, aby upewnić się, że sesja nie jest narażona na zawartość tabeli wstawioną przez poprzednią sesję z tym samym session_id. Ważne jest, aby utworzyć tabelę zoptymalizowaną pod kątem pamięci w czasie wdrażania, a nie w czasie wykonywania, aby uniknąć obciążenia kompilacyjnego związanego z tworzeniem tabeli. - Usuń instrukcje
DROP TABLE #tempSessionC
z kodu. Opcjonalnie możesz wstawić instrukcjęDELETE FROM dbo.soSessionC
w przypadku, gdy rozmiar pamięci jest potencjalnym problemem.
D. Scenariusz: zmienna tabeli może być MEMORY_OPTIMIZED=ON
Tradycyjna zmienna tabeli reprezentuje tabelę w tempdb
bazie danych. Aby uzyskać znacznie większą wydajność, można zoptymalizować zmienną tabeli w pamięci.
Oto język T-SQL dla tradycyjnej zmiennej tabeli. Jego zakres kończy się, gdy skończy się partia lub sesja.
DECLARE @tvTableD TABLE (
Column1 INT NOT NULL,
Column2 CHAR (10));
Konwertowanie wbudowanego na jawne
Mówi się, że poprzednia składnia tworzy zmienną tabeli inline. Składnia śródliniowa nie obsługuje optymalizacji pamięci. Przekonwertujmy składnię śródliniową na jawną składnię typu.
Zakres: Definicja TYPU utworzona przez pierwszą partię rozdzielaną jest zachowywana nawet po zamknięciu i ponownym uruchomieniu serwera. Ale po pierwszym ograniczniku go zadeklarowana tabela @tvTableC utrzymuje się tylko do momentu osiągnięcia następnego kroku i zakończenia partii.
CREATE TYPE dbo.typeTableD AS TABLE (
Column1 INT NOT NULL,
Column2 CHAR (10));
GO
SET NOCOUNT ON;
DECLARE @tvTableD AS dbo.typeTableD;
INSERT INTO @tvTableD (Column1) VALUES (1), (2);
SELECT * FROM @tvTableD;
GO
D.2 Przekształć dane zapisane na dysku na zoptymalizowane pod kątem pamięci
Zmienna tabeli zoptymalizowana pod kątem pamięci nie znajduje się w obiekcie tempdb
. Optymalizacja pamięci powoduje zwiększenie szybkości, które są często 10 razy szybsze lub więcej.
Konwersja do zoptymalizowanej pamięci jest realizowana w zaledwie jednym kroku. Rozszerz jawne tworzenie typu w następujący sposób, co dodaje:
- Indeks. Ponownie każda tabela zoptymalizowana pod kątem pamięci musi mieć co najmniej jeden indeks.
- MEMORY_OPTIMIZED = WŁĄCZONE.
CREATE TYPE dbo.typeTableD AS TABLE (
Column1 INT NOT NULL INDEX ix1,
Column2 CHAR (10))
WITH (MEMORY_OPTIMIZED = ON);
Gotowy.
E. Wymagania wstępne FILEGROUP dla programu SQL Server
W programie Microsoft SQL Server, aby korzystać z funkcji zoptymalizowanych pod kątem pamięci, baza danych musi mieć grupę plików zadeklarowaną za pomocą MEMORY_OPTIMIZED_DATA
.
- Usługa Azure SQL Database nie wymaga utworzenia tej grupy PLIKÓW.
Warunek wstępny: Poniższy kod Transact-SQL dla elementu FILEGROUP jest wymaganiem wstępnym dla długich przykładów kodu języka T-SQL w kolejnych sekcjach tego artykułu.
- Należy użyć SSMS.exe lub innego narzędzia, które może przesyłać język T-SQL.
- Wklej przykładowy kod T-SQL FILEGROUP do programu SSMS.
- Zmodyfikuj język T-SQL, aby zmienić określone nazwy i ścieżki katalogów na odpowiednie.
- Wszystkie katalogi w ścieżce NAZWA PLIKU muszą już istnieć, z wyjątkiem ostatniego katalogu, który nie może istnieć.
- Uruchom edytowany kod T-SQL.
- Nie trzeba uruchamiać pliku FILEGROUP T-SQL więcej niż jeden raz, nawet jeśli wielokrotnie dostosowujesz i ponownie uruchamiasz porównanie szybkości T-SQL w następnej podsekcji.
ALTER DATABASE InMemTest2
ADD FILEGROUP FgMemOptim3 CONTAINS MEMORY_OPTIMIZED_DATA;
GO
ALTER DATABASE InMemTest2
ADD FILE (NAME = N'FileMemOptim3a', FILENAME = N'C:\DATA\FileMemOptim3a'
-- C:\DATA\ preexisted.
) TO FILEGROUP FgMemOptim3;
GO
Poniższy skrypt tworzy dla Ciebie grupę plików i konfiguruje zalecane ustawienia bazy danych: enable-in-memory-oltp.sql
Aby uzyskać więcej informacji na temat ALTER DATABASE ... ADD
funkcji FILE i FILEGROUP, zobacz:
- ALTER DATABASE (Transact-SQL) Opcje plików i grup plików
- Grupa plików zoptymalizowana pod kątem pamięci
F. Szybki test w celu udowodnienia poprawy szybkości
Ta sekcja zawiera kod Transact-SQL, który można uruchomić w celu przetestowania i porównania szybkości zwiększenia dla INSERT-DELETE przy użyciu zmiennej tabeli zoptymalizowanej dla pamięci. Kod składa się z dwóch połówek, które są prawie takie same, z tym że w pierwszej połówce typ tabeli jest optymalizowany dla pamięci.
Test porównawczy trwa około 7 sekund. Aby uruchomić próbkę:
- Warunek wstępny: Musisz już uruchomić plik FILEGROUP T-SQL z poprzedniej sekcji.
- Uruchom następujący skrypt języka T-SQL INSERT-DELETE.
- Zwróć uwagę na instrukcję
GO 5001
, która ponownie przesyła kod T-SQL 5001 razy. Możesz dostosować liczbę i ponownie uruchomić.
Podczas uruchamiania skryptu w usłudze Azure SQL Database upewnij się, że uruchomiono z maszyny wirtualnej w tym samym regionie.
PRINT ' ';
PRINT '---- Next, memory-optimized, faster. ----';
DROP TYPE IF EXISTS dbo.typeTableC_mem;
GO
CREATE TYPE dbo.typeTableC_mem -- !! Memory-optimized.
AS TABLE (
Column1 INT NOT NULL INDEX ix1,
Column2 CHAR(10)
)
WITH (MEMORY_OPTIMIZED = ON);
GO
DECLARE @dateString_Begin NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_Begin,
' = Begin time, _mem.'
);
GO
SET NOCOUNT ON;
DECLARE @tvTableC dbo.typeTableC_mem;-- !!
INSERT INTO @tvTableC (Column1) VALUES (1), (2);
INSERT INTO @tvTableC (Column1) VALUES (3), (4);
DELETE @tvTableC;GO 5001
DECLARE @dateString_End NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_End,
' = End time, _mem.'
);
GO
DROP TYPE IF EXISTS dbo.typeTableC_mem;
GO
---- End memory-optimized.
-------------------------------------------------
---- Start traditional on-disk.
PRINT ' ';
PRINT '---- Next, tempdb based, slower. ----';
DROP TYPE IF EXISTS dbo.typeTableC_tempdb;
GO
CREATE TYPE dbo.typeTableC_tempdb -- !! Traditional tempdb.
AS TABLE (
Column1 INT NOT NULL,
Column2 CHAR(10)
);
GO
DECLARE @dateString_Begin NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_Begin,
' = Begin time, _tempdb.'
);
GO
SET NOCOUNT ON;
DECLARE @tvTableC dbo.typeTableC_tempdb;-- !!
INSERT INTO @tvTableC (Column1) VALUES (1), (2);
INSERT INTO @tvTableC (Column1) VALUES (3), (4);
DELETE @tvTableC;
GO 5001
DECLARE @dateString_End NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_End,
' = End time, _tempdb.'
);
GO
DROP TYPE IF EXISTS dbo.typeTableC_tempdb;
GO
PRINT '---- Tests done. ----';
GO
Oto zestaw wyników.
---- Next, memory-optimized, faster. ----
2016-04-20 00:26:58.033 = Begin time, _mem.
Beginning execution loop
Batch execution completed 5001 times.
2016-04-20 00:26:58.733 = End time, _mem.
---- Next, tempdb based, slower. ----
2016-04-20 00:26:58.750 = Begin time, _tempdb.
Beginning execution loop
Batch execution completed 5001 times.
2016-04-20 00:27:05.440 = End time, _tempdb.
---- Tests done. ----
G. Przewidywanie aktywnego użycia pamięci
Możesz dowiedzieć się, jak przewidzieć potrzeby aktywnej pamięci tabel zoptymalizowanych pod kątem pamięci przy użyciu następujących zasobów:
- Oszacowanie wymagań dotyczących pamięci dla tabel Memory-Optimized
- Rozmiar tabeli i wiersza w tabelach zoptymalizowanych pod kątem pamięci
W przypadku większych zmiennych tabeli indeksy nieklastrowane używają większej ilości pamięci niż w przypadku tabel zoptymalizowanych pod kątem pamięci. Tym większa liczba wierszy i klucz indeksu, tym większa jest różnica.
Jeśli dostęp do zmiennej tabeli zoptymalizowanej pod kątem pamięci jest uzyskiwany tylko z jedną dokładną wartością klucza na dostęp, indeks skrótu może być lepszym wyborem niż indeks nieklastrowany. Jednak jeśli nie możesz oszacować odpowiedniej wartości dla BUCKET_COUNT, indeks nierozproszony (NONCLUSTERED) jest dobrym drugim wyborem.
Treści powiązane
- Przykładowa baza danych dla In-Memory OLTP
- Definiowanie trwałości obiektów Memory-Optimized
- Zbiorcza aktualizacja mająca na celu wyeliminowanie prawdopodobieństwa wystąpienia nieprawidłowych błędów braku pamięci, ogłoszona na blogu we wrześniu 2017 r.
- KB3177312 — wersje kompilacji programu SQL Server 2016