Wskazówki dotyczące tabel (Transact-SQL)
Dotyczy:sql ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL Database w usłudze Microsoft Fabric
Wskazówki dotyczące tabel są używane do zastępowania domyślnego zachowania optymalizatora zapytań podczas instrukcji języka manipulowania danymi (DML). Można określić metodę blokowania, co najmniej jeden indeks, operację przetwarzania zapytań, taką jak skanowanie tabeli lub wyszukiwanie indeksu lub inne opcje. Wskazówki dotyczące tabeli są określone w klauzuli FROM
instrukcji DML i mają wpływ tylko na tabelę lub widok, do którego odwołuje się ta klauzula.
Ostrożność
Ponieważ optymalizator zapytań programu SQL Server zazwyczaj wybiera najlepszy plan wykonania zapytania, zalecamy, aby wskazówki były używane tylko jako ostateczność dla doświadczonych deweloperów i administratorów baz danych.
Dotyczy:
Transact-SQL konwencje składni
Składnia
WITH ( <table_hint> [ [ , ] ...n ] )
<table_hint> ::=
{ NOEXPAND
| INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
| FORCESEEK [ ( <index_value> ( <index_column_name> [ , ... ] ) ) ]
| FORCESCAN
| HOLDLOCK
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SNAPSHOT
| SPATIAL_WINDOW_MAX_CELLS = <integer_value>
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
<table_hint_limited> ::=
{
KEEPIDENTITY
| KEEPDEFAULTS
| HOLDLOCK
| IGNORE_CONSTRAINTS
| IGNORE_TRIGGERS
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SNAPSHOT
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
Argumenty
WITH ( <table_hint> ) [ , ] ...n ]
W przypadku niektórych wyjątków wskazówki dotyczące tabeli są obsługiwane w klauzuli FROM
tylko wtedy, gdy wskazówki są określone za pomocą słowa kluczowego WITH
. Wskazówki dotyczące tabeli muszą być również określone nawiasami.
Ważny
Pominięcie słowa kluczowego WITH
jest przestarzałą funkcją: ta funkcja zostanie usunięta w przyszłej wersji programu SQL Server. Unikaj używania tej funkcji w nowych pracach programistycznych i zaplanuj modyfikowanie aplikacji, które obecnie korzystają z tej funkcji.
Poniższe wskazówki dotyczące tabeli są dozwolone z słowem kluczowym WITH
i bez tego słowa kluczowego: NOLOCK
, READUNCOMMITTED
, UPDLOCK
, REPEATABLEREAD
, SERIALIZABLE
, READCOMMITTED
, TABLOCK
, TABLOCKX
, PAGLOCK
, ROWLOCK
, NOWAIT
, READPAST
, XLOCK
, SNAPSHOT
i NOEXPAND
. Gdy te wskazówki tabeli są określone bez słowa kluczowego WITH
, wskazówki powinny być określone samodzielnie. Na przykład:
FROM t (TABLOCK)
Po określeniu wskazówki z inną opcją należy określić wskazówkę za pomocą słowa kluczowego WITH
:
FROM t WITH (TABLOCK, INDEX(myindex))
Zalecamy używanie przecinków między wskazówkami tabeli.
Ważny
Oddzielanie wskazówek spacjami zamiast przecinków jest przestarzałą funkcją: ta funkcja zostanie usunięta w przyszłej wersji programu SQL Server. Unikaj używania tej funkcji w nowych pracach programistycznych i zaplanuj modyfikowanie aplikacji, które obecnie korzystają z tej funkcji.
NOEXPAND
Określa, że wszystkie indeksowane widoki nie są rozwinięte w celu uzyskania dostępu do bazowych tabel, gdy optymalizator zapytań przetwarza zapytanie. Optymalizator zapytań traktuje widok jak tabela z indeksem klastrowanym.
NOEXPAND
dotyczy tylko widoków indeksowanych. Aby uzyskać więcej informacji, zobacz Use NOEXPAND.
INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
Składnia INDEX()
określa nazwy lub identyfikatory co najmniej jednego indeksu, które mają być używane przez optymalizator zapytań podczas przetwarzania instrukcji. Alternatywna składnia INDEX =
określa pojedynczą wartość indeksu. Można określić tylko jedną wskazówkę indeksu na tabelę.
Jeśli istnieje indeks klastrowany, INDEX(0)
wymusza skanowanie indeksu klastrowanego, a INDEX(1)
wymusza skanowanie lub wyszukiwanie klastrowanych indeksów. Jeśli żaden indeks klastrowany nie istnieje, INDEX(0)
wymusza skanowanie tabeli, a INDEX(1)
jest interpretowany jako błąd.
Jeśli wiele indeksów jest używanych na jednej liście wskazówek, duplikaty są ignorowane, a pozostałe wymienione indeksy są używane do pobierania wierszy tabeli. Kolejność indeksów w wskazówce indeksu jest znacząca. Wiele wskazówek indeksu wymusza również indeks ANDing, a optymalizator zapytań stosuje jak najwięcej warunków dla każdego indeksu, do których uzyskuje się dostęp. Jeśli kolekcja sugerowanych indeksów nie zawiera wszystkich kolumn, do których odwołuje się zapytanie, pobiera się pobieranie pozostałych kolumn po pobraniu pozostałych kolumn po pobraniu wszystkich indeksowanych kolumn przez aparat bazy danych programu SQL Server.
Nuta
Gdy wskazówka indeksu odwołująca się do wielu indeksów jest używana w tabeli faktów w sprzężeniu gwiazdy, optymalizator ignoruje wskazówkę indeksu i zwraca komunikat ostrzegawczy. Ponadto indeks ORing nie jest dozwolony dla tabeli z określoną wskazówką indeksu.
Maksymalna liczba indeksów w wskazówce tabeli to 250 indeksów nieklastrowanych.
KEEPIDENTITY
Dotyczy tylko instrukcji INSERT
, gdy opcja BULK
jest używana z OPENROWSET.
Określa, że wartość tożsamości lub wartości w zaimportowanych plikach danych mają być używane dla kolumny tożsamości. Jeśli nie określono KEEPIDENTITY
, wartości tożsamości dla tej kolumny są weryfikowane, ale nie importowane, a optymalizator zapytań automatycznie przypisuje unikatowe wartości na podstawie wartości inicjacji i przyrostów określonych podczas tworzenia tabeli.
Ważny
Jeśli plik danych nie zawiera wartości kolumny tożsamości w tabeli lub widoku, a kolumna tożsamości nie jest ostatnią kolumną w tabeli, musisz pominąć kolumnę tożsamości. Aby uzyskać więcej informacji, zobacz Use a format file to skip a data field (SQL Server). Jeśli kolumna tożsamości zostanie pomyślnie pominięta, optymalizator zapytań automatycznie przypisze unikatowe wartości dla kolumny tożsamości do zaimportowanych wierszy tabeli.
Przykład, który używa tej wskazówki w instrukcji INSERT ... SELECT * FROM OPENROWSET(BULK...)
, zobacz Zachowaj wartości tożsamości podczas zbiorczego importowania danych (SQL Server).
Aby uzyskać informacje na temat sprawdzania wartości tożsamości dla tabeli, zobacz DBCC CHECKIDENT.
KEEPDEFAULTS
Dotyczy tylko instrukcji INSERT
, gdy opcja BULK
jest używana z OPENROWSET.
Określa wstawienie wartości domyślnej kolumny tabeli, jeśli istnieje, zamiast NULL
, gdy rekord danych nie ma wartości dla kolumny.
Aby zapoznać się z przykładem użycia tej wskazówki w instrukcji INSERT ... SELECT * FROM OPENROWSET(BULK...)
, zobacz Zachowaj wartości null lub wartości domyślne podczas importowania zbiorczego (SQL Server).
FORCESEEK [ ( <index_value> ( <index_column_name> [ , ...n ] ) ]
Określa, że optymalizator zapytań używa tylko operacji wyszukiwania indeksu jako ścieżki dostępu do danych w tabeli lub widoku.
Nuta
Począwszy od programu SQL Server 2008 R2 (10.50.x) z dodatkiem Service Pack 1, można również określić parametry indeksu. W takim przypadku optymalizator zapytań uwzględnia tylko operacje wyszukiwania indeksów za pośrednictwem określonego indeksu przy użyciu co najmniej określonych kolumn indeksu.
index_value
Nazwa indeksu lub wartość identyfikatora indeksu. Nie można określić identyfikatora indeksu 0 (sterta). Aby zwrócić nazwę indeksu lub identyfikator, wykonaj zapytanie dotyczące widoku wykazu
sys.indexes
.index_column_name
Nazwa kolumny indeksu do uwzględnienia w operacji wyszukiwania. Określanie
FORCESEEK
z parametrami indeksu jest podobne do używaniaFORCESEEK
z wskazówkąINDEX
. Można jednak uzyskać większą kontrolę nad ścieżką dostępu używaną przez optymalizator zapytań, określając zarówno indeks do wyszukiwania, jak i kolumny indeksu do rozważenia w operacji wyszukiwania. Optymalizator może w razie potrzeby rozważyć więcej kolumn. Jeśli na przykład określono indeks nieklastrowany, optymalizator może użyć kolumn klucza indeksu klastrowanego oprócz określonych kolumn.
Wskazówkę FORCESEEK
można określić w następujący sposób.
Składnia | Przykład | Opis |
---|---|---|
Bez indeksu lub wskazówki INDEX |
FROM dbo.MyTable WITH (FORCESEEK) |
Optymalizator zapytań uwzględnia tylko operacje wyszukiwania indeksu w celu uzyskania dostępu do tabeli lub wyświetlenia za pośrednictwem dowolnego odpowiedniego indeksu. |
W połączeniu z wskazówką INDEX |
FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex)) |
Optymalizator zapytań uwzględnia tylko operacje wyszukiwania indeksu w celu uzyskania dostępu do tabeli lub widoku za pośrednictwem określonego indeksu. |
Sparametryzowane przez określenie kolumn indeksu i indeksu | FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3))) |
Optymalizator zapytań uwzględnia tylko operacje wyszukiwania indeksu w celu uzyskania dostępu do tabeli lub widoku za pośrednictwem określonego indeksu przy użyciu co najmniej określonych kolumn indeksu. |
W przypadku korzystania z wskazówki FORCESEEK
(z parametrami indeksu lub bez ich) należy wziąć pod uwagę następujące wskazówki:
- Wskazówkę można określić jako wskazówkę tabeli lub jako wskazówkę zapytania. Aby uzyskać więcej informacji na temat wskazówek dotyczących zapytań, zobacz Wskazówki dotyczące zapytań (Transact-SQL).
- Aby zastosować
FORCESEEK
do widoku indeksowanego, należy również określić wskazówkęNOEXPAND
. - Wskazówkę można zastosować co najwyżej raz dla tabeli lub widoku.
- Nie można określić wskazówki dla zdalnego źródła danych. Błąd 7377 jest zwracany po określeniu
FORCESEEK
z wskazówką indeksu i błąd 8180 jest zwracany, gdyFORCESEEK
jest używany bez wskazówki indeksu. - Jeśli
FORCESEEK
nie znaleziono planów, zwracany jest błąd 8622.
Po określeniu FORCESEEK
z parametrami indeksu obowiązują następujące wytyczne i ograniczenia:
- Nie można określić wskazówki dla tabeli, która jest celem instrukcji
INSERT
,UPDATE
lubDELETE
. - Nie można określić wskazówki w połączeniu z wskazówką
INDEX
lub inną wskazówkąFORCESEEK
. - Należy określić co najmniej jedną kolumnę i musi być kolumną klucza wiodącego.
- Można określić dodatkowe kolumny indeksu, jednak nie można pominąć kolumn kluczowych. Jeśli na przykład określony indeks zawiera kolumny kluczy
a
,b
ic
, prawidłowa składnia będzie zawieraćFORCESEEK (MyIndex (a))
iFORCESEEK (MyIndex (a, b)
. Nieprawidłowa składnia obejmujeFORCESEEK (MyIndex (c))
iFORCESEEK (MyIndex (a, c)
. - Kolejność nazw kolumn określonych w wskazówce musi być zgodna z kolejnością kolumn w indeksie, do których odwołuje się odwołanie.
- Nie można określić kolumn, które nie mają definicji klucza indeksu. Na przykład w indeksie nieklastrowanym można określić tylko zdefiniowane kolumny klucza indeksu. Nie można określić kolumn kluczy klastrowanych, które są automatycznie uwzględnione w indeksie, ale mogą być używane przez optymalizator.
- Nie można określić indeksu magazynu kolumn zoptymalizowanego pod kątem pamięci xVelocity jako parametru indeksu. Zwracany jest błąd 366.
- Modyfikowanie definicji indeksu (na przykład przez dodawanie lub usuwanie kolumn) może wymagać modyfikacji zapytań odwołujących się do tego indeksu.
- Wskazówka uniemożliwia optymalizatorowi rozważenie wszelkich indeksów przestrzennych lub XML w tabeli.
- Nie można określić wskazówki w połączeniu z wskazówką
FORCESCAN
. - W przypadku indeksów partycjonowanych kolumna partycjonowania niejawnie dodana przez program SQL Server nie może być określona w wskazówce
FORCESEEK
.
Ostrożność
Określanie FORCESEEK
z parametrami ogranicza liczbę planów, które mogą być brane pod uwagę przez optymalizatora więcej niż podczas określania FORCESEEK
bez parametrów. Może to spowodować wystąpienie błędu Plan cannot be generated
w kolejnych przypadkach.
FORCESCAN
Dotyczy: SQL Server 2008 R2 (10.50.x) z dodatkiem Service Pack 1 lub nowszym
Określa, że optymalizator zapytań używa tylko operacji skanowania indeksu jako ścieżki dostępu do tabeli lub widoku, do którego odwołuje się odwołanie. Wskazówka FORCESCAN
może być przydatna w przypadku zapytań, w których optymalizator nie docenia liczby wierszy, których dotyczy problem, i wybiera operację wyszukiwania, a nie operację skanowania. W takim przypadku ilość pamięci przyznanej dla operacji jest zbyt mała i ma to wpływ na wydajność zapytań.
FORCESCAN
można określić z lub bez wskazówki INDEX
. W połączeniu z wskazówką indeksu (INDEX = index_name, FORCESCAN
) optymalizator zapytań uwzględnia tylko ścieżki dostępu skanowania za pośrednictwem określonego indeksu podczas uzyskiwania dostępu do tabeli, do których odwołuje się odwołanie.
FORCESCAN
można określić za pomocą wskazówki indeksu INDEX(0)
w celu wymuszenia operacji skanowania tabeli podstawowej.
W przypadku partycjonowanych tabel i indeksów FORCESCAN
są stosowane po wyeliminowaniu partycji za pomocą oceny predykatu zapytania. Oznacza to, że skanowanie jest stosowane tylko do pozostałych partycji, a nie do całej tabeli.
Wskazówka FORCESCAN
ma następujące ograniczenia:
- Nie można określić wskazówki dla tabeli, która jest celem instrukcji
INSERT
,UPDATE
lubDELETE
. - Wskazówka nie może być używana z więcej niż jedną wskazówką indeksu.
- Wskazówka uniemożliwia optymalizatorowi zapytań rozważenie wszelkich indeksów przestrzennych lub XML w tabeli.
- Nie można określić wskazówki dla zdalnego źródła danych.
- Nie można określić wskazówki w połączeniu z wskazówką
FORCESEEK
.
BLOKADA BLOKADY
Odpowiednik SERIALIZABLE
. Aby uzyskać więcej informacji, zobacz SERIALIZABLE w dalszej części tego artykułu.
HOLDLOCK
dotyczy tylko tabeli lub widoku, dla którego jest określony, i tylko przez czas trwania transakcji zdefiniowanej przez instrukcję, w której jest używana.
HOLDLOCK
nie można użyć w instrukcji SELECT, która zawiera opcję FOR BROWSE
.
IGNORE_CONSTRAINTS
Dotyczy tylko instrukcji INSERT
, gdy opcja BULK
jest używana z OPENROWSET.
Określa, że operacja importowania zbiorczego ignoruje wszelkie ograniczenia w tabeli. Domyślnie INSERT
sprawdza unikatowych ograniczeń i sprawdza ograniczenia i ograniczenia klucza podstawowego i obcego. Po określeniu IGNORE_CONSTRAINTS
dla operacji importowania zbiorczego INSERT
zignorować te ograniczenia w tabeli docelowej. Nie można wyłączyć ograniczeń UNIQUE
, PRIMARY KEY
lub NOT NULL
.
Jeśli dane wejściowe zawierają wiersze naruszające ograniczenia, warto wyłączyć CHECK
i FOREIGN KEY
ograniczenia. Wyłączenie ograniczeń CHECK
i FOREIGN KEY
umożliwia zaimportowanie danych, a następnie użycie instrukcji Transact-SQL w celu wyczyszczenia danych.
Jednak gdy ograniczenia CHECK
i FOREIGN KEY
są ignorowane, każde zignorowane ograniczenie w tabeli jest oznaczone jako is_not_trusted
w widoku sys.check_constraints lub sys.foreign_keys katalogu po operacji. W pewnym momencie należy sprawdzić ograniczenia dla całej tabeli. Jeśli tabela nie była pusta przed operacją importowania zbiorczego, koszt zmiany ograniczenia może przekroczyć koszt zastosowania CHECK
i FOREIGN KEY
ograniczeń do danych przyrostowych.
IGNORE_TRIGGERS
Dotyczy tylko instrukcji INSERT
, gdy opcja BULK
jest używana z OPENROWSET.
Określa, że wszystkie wyzwalacze zdefiniowane w tabeli są ignorowane przez operację importowania zbiorczego. Domyślnie INSERT
stosuje wyzwalacze.
Użyj IGNORE_TRIGGERS
tylko wtedy, gdy aplikacja nie zależy od żadnych wyzwalaczy, a maksymalizacja wydajności jest ważna.
NOLOCK
Odpowiednik READUNCOMMITTED
. Aby uzyskać więcej informacji, zobacz READUNCOMMITTED w dalszej części tego artykułu.
Nuta
W przypadku instrukcji UPDATE
lub DELETE
: ta funkcja zostanie usunięta w przyszłej wersji programu SQL Server. Unikaj używania tej funkcji w nowych pracach programistycznych i zaplanuj modyfikowanie aplikacji, które obecnie korzystają z tej funkcji.
NOWAIT
Nakazuje aparatowi bazy danych zwrócenie komunikatu zaraz po napotkaniu blokady w tabeli.
NOWAIT
jest odpowiednikiem określania SET LOCK_TIMEOUT 0
dla określonej tabeli. Wskazówka NOWAIT
nie działa, gdy dołączono również wskazówkę TABLOCK
. Aby zakończyć zapytanie bez oczekiwania podczas korzystania z wskazówki TABLOCK
, należy poprzeć zapytanie SET LOCK_TIMEOUT 0;
.
STRONICOWANIE
Pobiera blokady stron, w których pojedyncze blokady są zwykle wykonywane w wierszach lub kluczach albo zwykle jest wykonywana pojedyncza blokada tabeli. Domyślnie używa trybu blokady odpowiedniego dla operacji. Po określeniu w transakcjach działających na poziomie izolacji SNAPSHOT
blokady stron nie są wykonywane, chyba że PAGLOCK
jest połączona z innymi wskazówkami tabeli, które wymagają blokad, takich jak UPDLOCK
i HOLDLOCK
.
READCOMMITTED
Określa, że operacje odczytu są zgodne z regułami dla poziomu izolacji READ COMMITTED
przy użyciu blokady lub przechowywania wersji wierszy. Jeśli opcja bazy danych READ_COMMITTED_SNAPSHOT
jest OFF
, aparat bazy danych uzyskuje udostępnione blokady w miarę odczytywania danych i zwalnia te blokady po zakończeniu operacji odczytu. Jeśli opcja bazy danych READ_COMMITTED_SNAPSHOT
jest ON
, aparat bazy danych nie uzyskuje blokad i używa przechowywania wersji wierszy. Aby uzyskać więcej informacji na temat poziomów izolacji, zobacz SET TRANSACTION ISOLATION LEVEL.
Nuta
W przypadku instrukcji UPDATE
lub DELETE
: ta funkcja zostanie usunięta w przyszłej wersji programu SQL Server. Unikaj używania tej funkcji w nowych pracach programistycznych i zaplanuj modyfikowanie aplikacji, które obecnie korzystają z tej funkcji.
READCOMMITTEDLOCK
Określa, że operacje odczytu są zgodne z regułami dla poziomu izolacji READ COMMITTED
przy użyciu blokady. Aparat bazy danych uzyskuje udostępnione blokady podczas odczytywania danych i zwalnia te blokady po zakończeniu operacji odczytu, niezależnie od ustawienia opcji READ_COMMITTED_SNAPSHOT
bazy danych. Aby uzyskać więcej informacji na temat poziomów izolacji, zobacz SET TRANSACTION ISOLATION LEVEL. Nie można określić tej wskazówki w tabeli docelowej instrukcji INSERT
; Zwracany jest błąd 4140.
READPAST
Określa, że aparat bazy danych nie odczytuje wierszy, które są zablokowane przez inne transakcje. Po określeniu READPAST
blokady na poziomie wiersza są pomijane, ale blokady na poziomie strony nie są pomijane. Oznacza to, że aparat bazy danych pomija wcześniejsze wiersze zamiast blokować bieżącą transakcję do momentu zwolnienia blokad. Załóżmy na przykład, że tabela T1
zawiera jedną kolumnę całkowitą z wartościami 1, 2, 3, 4, 5. Jeśli transakcja A zmienia wartość od 3 do 8, ale nie została jeszcze zatwierdzona, SELECT * FROM T1 (READPAST)
zwraca wartości 1, 2, 4, 5.
READPAST
służy głównie do zmniejszania rywalizacji o blokowanie podczas implementowania kolejki roboczej korzystającej z tabeli programu SQL Server. Czytnik kolejek, który używa READPAST
pomija wcześniejsze wpisy kolejki zablokowane przez inne transakcje do następnego dostępnego wpisu kolejki, bez konieczności oczekiwania na zwolnienie blokad przez inne transakcje.
READPAST
można określić dla dowolnej tabeli, do których odwołuje się instrukcja UPDATE
lub DELETE
, oraz dowolnej tabeli, do których odwołuje się klauzula FROM
. Po określeniu w instrukcji UPDATE
READPAST
jest stosowany tylko podczas odczytywania danych w celu zidentyfikowania rekordów do zaktualizowania, niezależnie od tego, gdzie w instrukcji jest określona.
READPAST
nie można określić dla tabel w klauzuli INTO
instrukcji INSERT
. Aktualizowanie lub usuwanie operacji korzystających z READPAST
może blokować odczytywanie kluczy obcych lub indeksowanych widoków lub modyfikowanie indeksów pomocniczych.
READPAST
można określić tylko w transakcjach działających na poziomie izolacji READ COMMITTED
lub REPEATABLE READ
. Po określeniu w transakcjach działających na poziomie izolacji SNAPSHOT
READPAST
należy połączyć z innymi wskazówkami tabeli, które wymagają blokad, takich jak UPDLOCK
i HOLDLOCK
.
Nie można określić wskazówek tabeli READPAST
, gdy opcja READ_COMMITTED_SNAPSHOT
bazy danych jest ustawiona na ON
, a jeden z następujących warunków jest spełniony:
- Poziom izolacji transakcji sesji jest
READ COMMITTED
. - Wskazówka tabeli
READCOMMITTED
jest również określona w zapytaniu.
Aby określić wskazówkę READPAST
w tych przypadkach, usuń wskazówkę tabeli READCOMMITTED
, jeśli istnieje, i dołącz wskazówkę tabeli READCOMMITTEDLOCK
w zapytaniu.
READUNCOMMITTED
Określa, że brudne odczyty są dozwolone. Nie są wystawiane blokady udostępnione, aby uniemożliwić innym transakcjom modyfikowanie danych odczytanych przez bieżącą transakcję, a blokady wyłączne ustawione przez inne transakcje nie blokują bieżącej transakcji odczytywania zablokowanych danych. Zezwolenie na zanieczyszczone odczyty może spowodować większą współbieżność, ale kosztem odczytywania modyfikacji danych, które następnie są wycofane przez inne transakcje. Może to generować błędy dla transakcji, przedstawiać użytkownikom dane, które nigdy nie zostały zatwierdzone, lub spowodować, że użytkownicy będą widzieć rekordy dwa razy (lub w ogóle nie).
READUNCOMMITTED
i wskazówki NOLOCK
dotyczą tylko blokad danych. Wszystkie zapytania, w tym zapytania z wskazówkami READUNCOMMITTED
i NOLOCK
, uzyskują blokady Sch-S (stabilność schematu) podczas kompilacji i wykonywania. W związku z tym zapytania są blokowane, gdy współbieżna transakcja przechowuje blokadę Sch-M (modyfikacja schematu) w tabeli. Na przykład operacja języka definicji danych (DDL) uzyskuje blokadę Sch-M przed zmodyfikowaniem informacji o schemacie tabeli. Wszystkie zapytania współbieżne, w tym zapytania uruchamiane przy użyciu READUNCOMMITTED
lub wskazówek NOLOCK
, są blokowane podczas próby uzyskania blokady Sch-S. Z drugiej strony zapytanie zawierające blokadę Sch-S blokuje współbieżną transakcję, która próbuje uzyskać blokadę Sch-M.
READUNCOMMITTED
i NOLOCK
nie można określić dla tabel zmodyfikowanych przez operacje wstawiania, aktualizowania lub usuwania. Optymalizator zapytań programu SQL Server ignoruje wskazówki dotyczące READUNCOMMITTED
i NOLOCK
w klauzuli FROM
, która ma zastosowanie do tabeli docelowej instrukcji UPDATE
lub DELETE
.
Nuta
Obsługa użycia wskazówek dotyczących READUNCOMMITTED
i NOLOCK
w klauzuli FROM
, która ma zastosowanie do tabeli docelowej instrukcji UPDATE
lub DELETE
zostanie usunięta w przyszłej wersji programu SQL Server. Unikaj używania tych wskazówek w tym kontekście w ramach nowych prac programistycznych i zaplanuj modyfikowanie aplikacji, które obecnie ich używają.
Rywalizację o blokowanie można zminimalizować, chroniąc transakcje przed brudnymi operacjami odczytu niezatwierdzonych modyfikacji danych przy użyciu jednej z następujących opcji:
- Poziom izolacji
READ COMMITTED
z ustawioną opcją bazy danychREAD_COMMITTED_SNAPSHOT
ON
. - Poziom izolacji
SNAPSHOT
.
Aby uzyskać więcej informacji na temat poziomów izolacji, zobacz SET TRANSACTION ISOLATION LEVEL.
Nuta
Jeśli podczas READUNCOMMITTED
określono komunikat o błędzie 601, rozwiąż go tak, jak w przypadku błędu zakleszczenia (komunikatu o błędzie 1205) i spróbuj ponownie wykonać instrukcję.
POWTARZALNY ODCZYT
Określa, że skanowanie jest wykonywane przy użyciu tej samej semantyki blokowania co transakcja uruchomiona na REPEATABLE READ
poziomie izolacji. Aby uzyskać więcej informacji na temat poziomów izolacji, zobacz SET TRANSACTION ISOLATION LEVEL.
DULKA
Określa, że blokady wierszy są wykonywane, gdy zwykle są pobierane blokady strony lub tabeli. Po określeniu w transakcjach działających na poziomie izolacji SNAPSHOT
blokady wierszy nie są wykonywane, chyba że ROWLOCK
jest połączona z innymi wskazówkami tabeli, które wymagają blokad, takich jak UPDLOCK
i HOLDLOCK
.
ROWLOCK
nie można używać z tabelą z klastrowanym indeksem magazynu kolumn. Poniższy przykład zwraca błąd 651 do aplikacji.
UPDATE [dbo].[FactResellerSalesXL_CCI] WITH (ROWLOCK)
SET UnitPrice = 50
WHERE ProductKey = 150;
SERIALIZACJI
Odpowiednik HOLDLOCK
. Sprawia, że udostępnione blokady są bardziej restrykcyjne przez ich przechowywanie do momentu zakończenia transakcji, zamiast zwalniania udostępnionej blokady, gdy tylko wymagana tabela lub strona danych nie jest już potrzebna, niezależnie od tego, czy transakcja została ukończona, czy nie. Skanowanie jest wykonywane przy użyciu tej samej semantyki co transakcja uruchomiona na poziomie izolacji SERIALIZABLE
. Aby uzyskać więcej informacji na temat poziomów izolacji, zobacz SET TRANSACTION ISOLATION LEVEL.
MIGAWKA
Dotyczy: SQL Server 2014 (12.x) i nowsze wersje
Tabela zoptymalizowana pod kątem pamięci jest dostępna w SNAPSHOT
izolacji.
SNAPSHOT
można używać tylko z tabelami zoptymalizowanymi pod kątem pamięci (nie z tabelami opartymi na dyskach), jak pokazano w poniższym przykładzie. Aby uzyskać więcej informacji, zobacz wprowadzenie do tabel Memory-Optimized.
SELECT *
FROM dbo.Customers AS c WITH (SNAPSHOT)
LEFT OUTER JOIN dbo.[Order History] AS oh
ON c.customer_id = oh.customer_id;
SPATIAL_WINDOW_MAX_CELLS = <integer_value>
Dotyczy: SQL Server 2012 (11.x) i nowsze wersje
Określa maksymalną liczbę komórek do użycia na potrzeby tessellating obiektu geometrii lub geografii. <integer_value> jest wartością z zakresu od 1 do 8192.
Ta opcja umożliwia precyzyjne dostrajanie czasu wykonywania zapytania przez dostosowanie kompromisu między podstawowym i pomocniczym czasem wykonywania filtru. Większa liczba zmniejsza pomocniczy czas wykonywania filtru, ale zwiększa czas filtru podstawowego wykonywania, a mniejsza liczba zmniejsza czas wykonywania filtru podstawowego, ale zwiększa wykonywanie pomocniczego filtru. W przypadku gęstszych danych przestrzennych większa liczba powinna generować krótszy czas wykonywania, dając lepsze przybliżenie podstawowego filtru i skrócenie pomocniczego czasu wykonywania filtru. W przypadku większej ilości rozrzedniejszych danych niższa liczba zmniejsza czas wykonywania filtru podstawowego.
Ta opcja działa zarówno w przypadku ręcznych, jak i automatycznych tessellacji siatki.
TABLOCK
Określa, że uzyskana blokada jest stosowana na poziomie tabeli. Typ nabytej blokady zależy od wykonywanej instrukcji. Na przykład instrukcja SELECT
może uzyskać udostępnioną blokadę. Określając TABLOCK
, blokada udostępniona jest stosowana do całej tabeli zamiast na poziomie wiersza lub strony. Jeśli HOLDLOCK
jest również określona, blokada tabeli jest przechowywana do końca transakcji.
Podczas importowania danych do sterta przy użyciu instrukcji INSERT INTO <target_table> SELECT <columns> FROM <source_table>
można włączyć minimalne rejestrowanie i optymalne blokowanie dla instrukcji, określając wskazówkę TABLOCK
dla tabeli docelowej. Ponadto model odzyskiwania bazy danych musi być ustawiony na prosty lub rejestrowany zbiorczo. Wskazówka TABLOCK
umożliwia również równoległe wstawianie do stertów lub klastrowanych indeksów magazynu kolumn. Aby uzyskać więcej informacji, zobacz INSERT.
W przypadku użycia z OPENROWSET dostawcy zestawów wierszy zbiorczych do importowania danych do tabeli, TABLOCK
umożliwia wielu klientom równoczesne ładowanie danych do tabeli docelowej przy użyciu zoptymalizowanego rejestrowania i blokowania. Aby uzyskać więcej informacji, zobacz Wymagania wstępne dotyczące minimalnego rejestrowania w importowaniu zbiorczym.
TABLOCKX
Określa, że na stole jest pobierana blokada wyłączna.
UPDLOCK
Określa, że blokady aktualizacji mają być pobierane i przechowywane do momentu zakończenia transakcji.
UPDLOCK
przyjmuje blokady aktualizacji dla operacji odczytu tylko na poziomie wiersza lub na poziomie strony. Jeśli UPDLOCK
jest w połączeniu z TABLOCK
lub blokada na poziomie tabeli zostanie podjęta z jakiegoś innego powodu, zamiast tego zostanie podjęta blokada na wyłączność (X).
Po określeniu UPDLOCK
wskazówki dotyczące poziomu izolacji READCOMMITTED
i READCOMMITTEDLOCK
są ignorowane. Jeśli na przykład poziom izolacji sesji jest ustawiony na SERIALIZABLE
, a zapytanie określa (UPDLOCK
, READCOMMITTED
), wskazówka READCOMMITTED
jest ignorowana, a transakcja jest uruchamiana przy użyciu poziomu izolacji SERIALIZABLE
.
XLOCK
Określa, że blokady wyłącznych mają być pobierane i przechowywane do momentu zakończenia transakcji. W przypadku określenia z ROWLOCK
, PAGLOCK
lub TABLOCK
blokady wyłączne mają zastosowanie do odpowiedniego poziomu szczegółowości.
Uwagi
Wskazówki dotyczące tabeli są ignorowane, jeśli tabela nie jest uzyskiwana przez plan zapytania. Może to być spowodowane tym, że optymalizator nie może w ogóle uzyskać dostępu do tabeli lub ponieważ zamiast tego uzyskuje się dostęp do indeksowanego widoku. W tym ostatnim przypadku dostęp do indeksowanego widoku można uniemożliwić przy użyciu wskazówki OPTION (EXPAND VIEWS)
zapytania.
Wszystkie wskazówki dotyczące blokady są propagowane do wszystkich tabel i widoków, do których uzyskuje się dostęp w ramach planu zapytania, w tym tabel i widoków, do których odwołuje się widok. Ponadto program SQL Server wykonuje odpowiednie testy spójności blokady.
Wskazówki dotyczące blokad ROWLOCK
, UPDLOCK
i XLOCK
, które uzyskują blokady na poziomie wiersza, mogą umieszczać blokady na kluczach indeksu, a nie na rzeczywistych wierszach danych. Jeśli na przykład tabela ma indeks nieklastrowany, a instrukcja SELECT
korzystająca z wskazówki blokady jest obsługiwana przez indeks obejmujący, blokada jest uzyskiwana na kluczu indeksu indeksu w indeksie obejmującym, a nie w wierszu danych w tabeli bazowej.
Jeśli tabela zawiera obliczone kolumny obliczane przez wyrażenia lub funkcje, które uzyskują dostęp do kolumn w innych tabelach, wskazówki tabeli nie są używane w tych tabelach i nie są propagowane. Na przykład w tabeli w zapytaniu określono wskazówkę NOLOCK
tabeli. Ta tabela zawiera kolumny obliczeniowe obliczane przez kombinację wyrażeń i funkcji, które uzyskują dostęp do kolumn w innej tabeli. Tabele, do których odwołuje się wyrażenia i funkcje, nie używają wskazówek tabeli NOLOCK
podczas uzyskiwania dostępu.
Program SQL Server nie zezwala na więcej niż jedną wskazówkę tabeli z każdej z następujących grup dla każdej tabeli w klauzuli FROM
:
- Wskazówki dotyczące stopnia szczegółowości:
PAGLOCK
,NOLOCK
,READCOMMITTEDLOCK
,ROWLOCK
,TABLOCK
lubTABLOCKX
. - Wskazówki dotyczące poziomu izolacji:
HOLDLOCK
,NOLOCK
,READCOMMITTED
,REPEATABLEREAD
,SERIALIZABLE
.
Przefiltrowane wskazówki dotyczące indeksu
Filtrowany indeks może służyć jako wskazówka do tabeli, ale powoduje, że optymalizator zapytań generuje błąd 8622, jeśli nie obejmuje wszystkich wierszy wybranych przez zapytanie. Poniżej przedstawiono przykład nieprawidłowej przefiltrowanej wskazówki indeksu. Przykład tworzy filtrowany indeks FIBillOfMaterialsWithComponentID
, a następnie używa go jako wskazówki indeksu dla instrukcji SELECT
. Filtrowany predykat indeksu zawiera wiersze danych dla identyfikatorów składników 533, 324 i 753. Predykat zapytania zawiera również wiersze danych dla identyfikatorów składników 533, 324 i 753, ale rozszerza zestaw wyników tak, aby zawierał identyfikatory składników 855 i 924, które nie znajdują się w filtrowanym indeksie. W związku z tym optymalizator zapytań nie może użyć filtrowanej wskazówki indeksu i generuje błąd 8622. Aby uzyskać więcej informacji, zobacz Tworzenie filtrowanych indeksów.
IF EXISTS (SELECT name FROM sys.indexes
WHERE name = N'FIBillOfMaterialsWithComponentID'
AND object_id = OBJECT_ID(N'Production.BillOfMaterials'))
DROP INDEX FIBillOfMaterialsWithComponentID
ON Production.BillOfMaterials;
GO
CREATE NONCLUSTERED INDEX [FIBillOfMaterialsWithComponentID]
ON Production.BillOfMaterials(ComponentID, StartDate, EndDate)
WHERE ComponentID IN (533, 324, 753);
GO
SELECT StartDate, ComponentID
FROM Production.BillOfMaterials
WITH (INDEX (FIBillOfMaterialsWithComponentID))
WHERE ComponentID IN (533, 324, 753, 855, 924);
GO
Optymalizator zapytań nie uwzględnia wskazówki dotyczącej indeksu, jeśli opcje SET
nie mają wymaganych wartości dla filtrowanych indeksów. Aby uzyskać więcej informacji, zobacz CREATE INDEX.
Używanie FUNKCJI NOEXPAND
NOEXPAND
dotyczy tylko widoków indeksowanych . Widok indeksowany to widok z unikatowym indeksem klastrowanym utworzonym na nim. Jeśli zapytanie zawiera odwołania do kolumn, które znajdują się zarówno w indeksowanym widoku, jak i w tabelach podstawowych, a optymalizator zapytań określa, że użycie indeksowanego widoku zapewnia najlepszą metodę wykonywania zapytania, optymalizator zapytań używa indeksu w widoku. Ta funkcja jest nazywana indeksowanym widokiem zgodnym z. Przed programem SQL Server 2016 (13.x) z dodatkiem Service Pack 1 automatyczne używanie widoku indeksowanego przez optymalizator zapytań jest obsługiwane tylko w określonych wersjach programu SQL Server. W programie SQL Server 2016 (13.x) z dodatkiem Service Pack 1 lub nowszym wszystkie wersje obsługują automatyczne korzystanie z indeksowanego widoku. Usługi Azure SQL Database i Azure SQL Managed Instance obsługują również automatyczne korzystanie z indeksowanych widoków bez określania wskazówki NOEXPAND
.
Aby uzyskać więcej informacji, zobacz Przewodnik po architekturze przetwarzania zapytań.
Aby uzyskać listę funkcji obsługiwanych przez wersje programu SQL Server w systemie Windows, zobacz:
- Editions i obsługiwane funkcje programu SQL Server 2022
- Editions i obsługiwane funkcje programu SQL Server 2019
- Editions i obsługiwane funkcje programu SQL Server 2017
- Editions i obsługiwane funkcje programu SQL Server 2016
Jednak aby optymalizator zapytań rozważył indeksowane widoki pod kątem dopasowania lub użyć indeksowanego widoku, do którego odwołuje się wskazówka NOEXPAND
, należy ustawić następujące opcje SET
na ON
.
- ANSI_NULLS
- ANSI_PADDING
- ANSI_WARNINGS
- ARITHABORT 1
- CONCAT_NULL_YIELDS_NULL
- QUOTED_IDENTIFIER
1ARITHABORT
jest niejawnie ustawiona na ON
po ustawieniu ANSI_WARNINGS
na wartość ON
. W związku z tym nie trzeba ręcznie dostosowywać tego ustawienia.
Ponadto należy ustawić opcję NUMERIC_ROUNDABORT
na OFF
.
Aby wymusić użycie indeksu dla widoku indeksowanego przez optymalizator zapytań, określ opcję NOEXPAND
. Ta wskazówka może być używana tylko wtedy, gdy widok jest również nazwany w zapytaniu. Program SQL Server nie udostępnia wskazówek, aby wymusić użycie określonego indeksowanego widoku w zapytaniu, które nie nazywa widoku bezpośrednio w klauzuli FROM
. Jednak optymalizator zapytań uwzględnia użycie widoków indeksowanych, nawet jeśli nie są one przywoływane bezpośrednio w zapytaniu. Aparat bazy danych programu SQL Server automatycznie tworzy statystyki tylko w widoku indeksowanym, gdy jest używana wskazówka tabeli NOEXPAND
. Pominięcie tej wskazówki może prowadzić do ostrzeżeń planu wykonania dotyczących brakujących statystyk, których nie można rozwiązać, tworząc statystyki ręcznie.
Podczas optymalizacji zapytań aparat bazy danych używa statystyk widoku, które zostały utworzone automatycznie lub ręcznie, gdy zapytanie odwołuje się bezpośrednio do widoku, a wskazówka NOEXPAND
jest używana.
Używanie wskazówki tabeli jako wskazówki dotyczącej zapytania
wskazówek tabeli można również określić jako wskazówkę zapytania przy użyciu klauzuli OPTION (TABLE HINT)
. Zalecamy użycie wskazówki tabeli jako wskazówki dotyczącej zapytania tylko w kontekście przewodnika planu . W przypadku zapytań ad hoc określ te wskazówki tylko jako wskazówki dotyczące tabeli. Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące zapytań.
Uprawnienia
Wskazówki dotyczące KEEPIDENTITY
, IGNORE_CONSTRAINTS
i IGNORE_TRIGGERS
wymagają ALTER
uprawnień w tabeli.
Przykłady
A. Użyj wskazówki TABLOCK, aby określić metodę blokowania
Poniższy przykład określa, że udostępniona blokada jest wykonywana w tabeli Production.Product
w bazie danych AdventureWorks2022 i jest przechowywana do końca instrukcji UPDATE
.
UPDATE Production.Product WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO
B. Użyj wskazówki FORCESEEK, aby określić operację wyszukiwania indeksu
W poniższym przykładzie użyto wskazówki FORCESEEK
bez określania indeksu, aby wymusić działanie optymalizatora zapytań w celu wykonania operacji wyszukiwania indeksu w tabeli Sales.SalesOrderDetail
w bazie danych AdventureWorks2022.
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESEEK)
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5
OR d.LineTotal < 1000.00);
GO
W poniższym przykładzie użyto wskazówki FORCESEEK
z indeksem, aby wymusić optymalizator zapytań wykonanie operacji wyszukiwania indeksu w określonej kolumnie indeksu i indeksu.
SELECT h.SalesOrderID,
h.TotalDue,
d.OrderQty
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d
WITH (FORCESEEK (PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID (SalesOrderID)))
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5
OR d.LineTotal < 1000.00);
GO
C. Użyj wskazówki FORCESCAN, aby określić operację skanowania indeksu
W poniższym przykładzie użyto wskazówki FORCESCAN
, aby wymusić, że optymalizator zapytań wykona operację skanowania w tabeli Sales.SalesOrderDetail
w bazie danych AdventureWorks2022.
SELECT h.SalesOrderID,
h.TotalDue,
d.OrderQty
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESCAN)
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5
OR d.LineTotal < 1000.00);
Powiązana zawartość
- OPENROWSET (Transact-SQL)
- wskazówki dotyczące (Transact-SQL)
- wskazówki dotyczące zapytań (Transact-SQL)