Rady k tabulce (Transact-SQL)
platí pro:SQL ServerAzure SQL Databaseazure SQL Managed InstanceSQL Database v Microsoft Fabric
Nápovědy k tabulce se používají k přepsání výchozího chování optimalizátoru dotazů během příkazu jazyka DML (Data Manipulat Language). Můžete zadat metodu uzamčení, jeden nebo více indexů, operaci zpracování dotazů, jako je prohledávání tabulky nebo hledání indexu nebo jiné možnosti. V klauzuli FROM
příkazu DML jsou uvedeny rady tabulky a ovlivňují pouze tabulku nebo zobrazení odkazované v této klauzuli.
Opatrnost
Vzhledem k tomu, že optimalizátor dotazů SQL Serveru obvykle vybírá nejlepší plán provádění dotazu, doporučujeme, aby se rady používaly pouze jako poslední možnost zkušenými vývojáři a správci databází.
platí pro:
Syntax
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 ]
S některými výjimkami jsou v klauzuli FROM
podporovány rady tabulky pouze v případě, že jsou nápovědy zadány pomocí klíčového slova WITH
. V závorkách je také nutné zadat nápovědu k tabulce.
Důležitý
Vynechání klíčového slova WITH
je zastaralá funkce: Tato funkce se odebere v budoucí verzi SQL Serveru. Nepoužívejte tuto funkci v nové vývojové práci a naplánujte úpravu aplikací, které tuto funkci aktuálně používají.
Následující rady tabulky jsou povoleny s klíčovým slovem WITH
a bez WITH
: NOLOCK
, READUNCOMMITTED
, UPDLOCK
, REPEATABLEREAD
, SERIALIZABLE
, READCOMMITTED
, TABLOCK
, TABLOCKX
, PAGLOCK
, ROWLOCK
, NOWAIT
, READPAST
, XLOCK
, SNAPSHOT
a NOEXPAND
. Pokud jsou tyto rady tabulky zadány bez klíčového slova WITH
, měly by být pokyny zadány samostatně. Například:
FROM t (TABLOCK)
Při zadání nápovědy s jinou možností je nutné zadat nápovědu pomocí klíčového slova WITH
:
FROM t WITH (TABLOCK, INDEX(myindex))
Doporučujeme použít čárky mezi radami tabulky.
Důležitý
Oddělení nápovědy mezerami místo čárkami je zastaralá funkce: Tato funkce se odebere v budoucí verzi SQL Serveru. Nepoužívejte tuto funkci v nové vývojové práci a naplánujte úpravu aplikací, které tuto funkci aktuálně používají.
NOEXPAND
Určuje, že se při zpracování dotazu optimalizátoru dotazů nezvětší žádná indexovaná zobrazení pro přístup k podkladovým tabulkám. Optimalizátor dotazů zachází s zobrazením jako s tabulkou s clusterovaným indexem.
NOEXPAND
platí jenom pro indexovaná zobrazení. Další informace naleznete v tématu Použití funkce NOEXPAND.
INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
Syntaxe INDEX()
určuje názvy nebo ID jednoho nebo více indexů, které se mají použít optimalizátorem dotazů při zpracování příkazu. Alternativní syntaxe INDEX =
určuje jednu hodnotu indexu. Pro každou tabulku je možné zadat pouze jeden tip indexu.
Pokud existuje clusterovaný index, INDEX(0)
vynutí kontrolu clusterovaného indexu a INDEX(1)
vynutí kontrolu nebo hledání clusterovaného indexu. Pokud neexistuje žádný clusterovaný index, INDEX(0)
vynutí prohledávání tabulky a INDEX(1)
se interpretuje jako chyba.
Pokud se v jednom seznamu nápovědy používá více indexů, budou duplicity ignorovány a zbývající uvedené indexy se použijí k načtení řádků tabulky. Pořadí indexů v nápovědě indexu je významné. Funkce ANDing indexu také vynucuje více tipů indexu a optimalizátor dotazů na každý index, ke které se přistupuje, použije co nejvíce podmínek. Pokud kolekce indexů s nápovědou neobsahuje všechny sloupce odkazované dotazem, provede se načtení pro načtení zbývajících sloupců po načtení všech indexovaných sloupců databázový stroj SQL Serveru.
Poznámka
Pokud se v tabulce faktů ve spojení hvězdičkou použije nápověda indexu odkazující na více indexů, optimalizátor ignoruje nápovědu indexu a vrátí zprávu s upozorněním. U tabulky se zadaným nápovědou indexu také není povolený index ORing.
Maximální počet indexů v nápovědě tabulky je 250 neclusterovaných indexů.
KEEPIDENTITY
Platí pouze v příkazu INSERT
, pokud je možnost BULK
použita s OPENROWSET.
Určuje, že hodnota identity nebo hodnoty v importovaném datovém souboru se použijí pro sloupec identity. Pokud není zadaný KEEPIDENTITY
, ověří se hodnoty identity pro tento sloupec, ale neimportují se a optimalizátor dotazů automaticky přiřadí jedinečné hodnoty na základě počátečních a přírůstkových hodnot zadaných během vytváření tabulky.
Důležitý
Pokud datový soubor neobsahuje hodnoty sloupce identity v tabulce nebo zobrazení a sloupec identity není posledním sloupcem v tabulce, musíte sloupec identity přeskočit. Další informace najdete v tématu Použití souboru formátu k přeskočení datového pole (SQL Server). Pokud se sloupec identity úspěšně přeskočí, optimalizátor dotazů automaticky přiřadí do importovaných řádků tabulky jedinečné hodnoty sloupce identity.
Příklad, který používá tento tip v příkazu INSERT ... SELECT * FROM OPENROWSET(BULK...)
, naleznete v tématu Zachovat hodnoty identity při hromadném importu dat (SQL Server).
Informace o kontrole hodnoty identity pro tabulku naleznete v tématu DBCC CHECKIDENT.
KEEPDEFAULTS
Platí pouze v příkazu INSERT
, pokud je možnost BULK
použita s OPENROWSET.
Určuje vložení výchozí hodnoty sloupce tabulky, pokud existuje, místo NULL
, když záznam dat nemá hodnotu sloupce.
Příklad, který používá tento tip v příkazu INSERT ... SELECT * FROM OPENROWSET(BULK...)
, naleznete v tématu Zachovat hodnoty null nebo výchozí hodnoty při hromadném importu (SQL Server).
FORCESEEK [ ( <index_value> ( <index_column_name> [ , ...n ] ) ]
Určuje, že optimalizátor dotazů používá jako přístupovou cestu k datům v tabulce nebo zobrazení pouze operaci hledání indexu.
Poznámka
Od verze SQL Server 2008 R2 (10.50.x) Service Pack 1 je možné zadat také parametry indexu. V takovém případě optimalizátor dotazů bere v úvahu pouze operace hledání indexu prostřednictvím zadaného indexu pomocí alespoň zadaných sloupců indexu.
index_value
Název indexu nebo hodnota ID indexu. ID indexu 0 (halda) nelze zadat. Pokud chcete vrátit název nebo ID indexu, zadejte dotaz na zobrazení katalogu
sys.indexes
.index_column_name
Název indexového sloupce, který se má zahrnout do operace hledání. Zadání
FORCESEEK
s parametry indexu je podobné použitíFORCESEEK
s nápovědouINDEX
. Můžete však dosáhnout větší kontroly nad cestou přístupu používanou optimalizátorem dotazů zadáním indexu, který se má vyhledat, a sloupce indexu, které je potřeba zvážit v operaci hledání. Optimalizátor může v případě potřeby zvážit více sloupců. Pokud je například zadaný neclusterovaný index, optimalizátor se může rozhodnout, že kromě zadaných sloupců použije sloupce clusterovaného indexového klíče.
Nápovědu FORCESEEK
lze zadat následujícími způsoby.
Syntax | Příklad | Popis |
---|---|---|
Bez nápovědy indexu nebo INDEX |
FROM dbo.MyTable WITH (FORCESEEK) |
Optimalizátor dotazů bere v úvahu pouze operace hledání indexů pro přístup k tabulce nebo zobrazení prostřednictvím libovolného relevantního indexu. |
Kombinace s nápovědou INDEX |
FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex)) |
Optimalizátor dotazů považuje pouze operace hledání indexů pro přístup k tabulce nebo zobrazení prostřednictvím zadaného indexu. |
Parametrizováno zadáním indexu a indexových sloupců | FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3))) |
Optimalizátor dotazů bere v úvahu pouze operace hledání indexů pro přístup k tabulce nebo zobrazení prostřednictvím zadaného indexu pomocí alespoň zadaných sloupců indexu. |
Při použití nápovědy FORCESEEK
(s parametry indexu nebo bez nich) zvažte následující pokyny:
- Nápovědu lze zadat jako nápovědu tabulky nebo jako nápovědu dotazu. Další informace o nápovědě k dotazům najdete v tématu Nápovědy k dotazům (Transact-SQL).
- Chcete-li použít
FORCESEEK
v indexovaném zobrazení, musí být zadán takéNOEXPAND
nápovědy. - Nápovědu lze použít maximálně na tabulku nebo zobrazení.
- Nápovědu nelze zadat pro vzdálený zdroj dat. Při zadání
FORCESEEK
s nápovědou indexu se vrátí chyba 7377 a při použitíFORCESEEK
bez nápovědy indexu se vrátí chyba 8180. - Pokud
FORCESEEK
způsobí, že se nenašly žádné plány, vrátí se chyba 8622.
Při zadání FORCESEEK
s parametry indexu platí následující pokyny a omezení:
- Nápovědu nelze zadat pro tabulku, která je cílem příkazu
INSERT
,UPDATE
neboDELETE
. - Nápovědu nelze zadat v kombinaci s nápovědou
INDEX
nebo jinou nápovědouFORCESEEK
. - Musí být zadán alespoň jeden sloupec a musí se jednat o počáteční klíčový sloupec.
- Další sloupce indexu je možné zadat, ale klíčové sloupce se nedají přeskočit. Například pokud zadaný index obsahuje klíčové sloupce
a
,b
ac
, platná syntaxe by zahrnovalaFORCESEEK (MyIndex (a))
aFORCESEEK (MyIndex (a, b)
. Neplatná syntaxe by zahrnovalaFORCESEEK (MyIndex (c))
aFORCESEEK (MyIndex (a, c)
. - Pořadí názvů sloupců zadaných v nápovědě musí odpovídat pořadí sloupců v odkazovaném indexu.
- Sloupce, které nejsou v definici klíče indexu, nelze zadat. Například v neclusterovaném indexu je možné zadat pouze definované sloupce klíče indexu. Sloupce clusterovaných klíčů, které jsou automaticky zahrnuty do indexu, nelze zadat, ale může je použít optimalizátor.
- Index columnstore optimalizovaný pro paměť xVelocity nelze zadat jako parametr indexu. Vrátí se chyba 366.
- Úprava definice indexu (například přidáním nebo odebráním sloupců) může vyžadovat úpravy dotazů, které na tento index odkazují.
- Tento tip brání optimalizátoru v zvážení libovolného prostorového indexu nebo indexu XML v tabulce.
- Nápovědu nelze zadat v kombinaci s nápovědou
FORCESCAN
. - U dělených indexů není možné v nápovědě k
FORCESEEK
zadat sloupec dělení implicitně přidaný SQL Serverem.
Opatrnost
Určení FORCESEEK
s parametry omezuje počet plánů, které může optimalizátor zvážit více než při zadávání FORCESEEK
bez parametrů. To může způsobit, že Plan cannot be generated
dojde k chybě ve více případech.
FORCESCAN
platí pro: SQL Server 2008 R2 (10.50.x) Service Pack 1 a novější verze
Určuje, že optimalizátor dotazů používá jako přístupovou cestu k odkazované tabulce nebo zobrazení pouze operaci prohledávání indexu. Nápověda FORCESCAN
může být užitečná pro dotazy, ve kterých optimalizátor podceňuje počet ovlivněných řádků a zvolí operaci hledání, a ne operaci prohledávání. Pokud k tomu dojde, množství paměti udělené pro operaci je příliš malé a je ovlivněn výkon dotazů.
FORCESCAN
lze zadat pomocí nebo bez nápovědy INDEX
. V kombinaci s nápovědou indexu (INDEX = index_name, FORCESCAN
), optimalizátor dotazů při přístupu k odkazované tabulce bere v úvahu pouze cesty přístupu přes zadaný index.
FORCESCAN
lze zadat pomocí INDEX(0)
nápovědy indexu k vynucení operace prohledávání tabulky na základní tabulce.
U dělených tabulek a indexů se FORCESCAN
použije po odstranění oddílů prostřednictvím vyhodnocení predikátu dotazu. To znamená, že kontrola se použije jenom na zbývající oddíly, a ne na celou tabulku.
Nápověda pro FORCESCAN
má následující omezení:
- Nápovědu nelze zadat pro tabulku, která je cílem příkazu
INSERT
,UPDATE
neboDELETE
. - Nápovědu nelze použít s více než jednou nápovědou indexu.
- Tento tip brání optimalizátoru dotazů v zvážení libovolného prostorového indexu nebo indexu XML v tabulce.
- Nápovědu nelze zadat pro vzdálený zdroj dat.
- Nápovědu nelze zadat v kombinaci s nápovědou
FORCESEEK
.
HOLDLOCK
Ekvivalent SERIALIZABLE
. Další informace naleznete v části SERIALIZABLE dále v tomto článku.
HOLDLOCK
se vztahuje pouze na tabulku nebo zobrazení, pro které je určena, a pouze po dobu trvání transakce definované příkazem, ve kterém se používá.
HOLDLOCK
nelze použít v příkazu SELECT, který obsahuje možnost FOR BROWSE
.
IGNORE_CONSTRAINTS
Platí pouze v příkazu INSERT
, pokud je možnost BULK
použita s OPENROWSET.
Určuje, že operace hromadného importu ignoruje všechna omezení v tabulce. Ve výchozím nastavení INSERT
kontroluje jedinečná omezení a omezení kontroly a omezení primárního a cizího klíče. Pokud je pro operaci hromadného importu zadán IGNORE_CONSTRAINTS
, INSERT
musí tato omezení v cílové tabulce ignorovat. Omezení UNIQUE
, PRIMARY KEY
nebo NOT NULL
nemůžete zakázat.
Pokud vstupní data obsahují řádky, které porušují omezení, může být vhodné zakázat CHECK
a FOREIGN KEY
omezení. Zakázáním omezení CHECK
a FOREIGN KEY
můžete data importovat a pak pomocí příkazů Transact-SQL data vyčistit.
Pokud jsou však CHECK
a FOREIGN KEY
omezení ignorována, každé ignorované omezení tabulky se po operaci označí jako is_not_trusted
v zobrazení katalogu sys.check_constraints nebo sys.foreign_keys. V určitém okamžiku byste měli zkontrolovat omezení celé tabulky. Pokud nebyla tabulka před hromadným importem prázdná, náklady na opětovné ověření omezení můžou překročit náklady na použití CHECK
a FOREIGN KEY
omezení přírůstkových dat.
IGNORE_TRIGGERS
Platí pouze v příkazu INSERT
, pokud je možnost BULK
použita s OPENROWSET.
Určuje, že všechny triggery definované v tabulce jsou ignorovány operací hromadného importu. Ve výchozím nastavení INSERT
použije triggery.
Použijte IGNORE_TRIGGERS
jenom v případě, že vaše aplikace nezávisí na žádných triggerech a maximalizaci výkonu je důležité.
NOLOCK
Ekvivalent READUNCOMMITTED
. Další informace najdete v tématu READUNCOMMITTED dále v tomto článku.
Poznámka
Pro příkazy UPDATE
nebo DELETE
: Tato funkce se odebere v budoucí verzi SQL Serveru. Nepoužívejte tuto funkci v nové vývojové práci a naplánujte úpravu aplikací, které tuto funkci aktuálně používají.
NOWAIT
Dává databázovému stroji pokyn, aby vrátil zprávu, jakmile bude v tabulce zjištěn zámek.
NOWAIT
odpovídá zadání SET LOCK_TIMEOUT 0
pro konkrétní tabulku. Nápovědu NOWAIT
nefunguje, pokud je zahrnuta také nápověda TABLOCK
. Pokud chcete ukončit dotaz bez čekání, když použijete nápovědu TABLOCK
, předkažte místo toho dotaz SET LOCK_TIMEOUT 0;
.
PAGLOCK
Přebírá zámky stránek, ať už jsou jednotlivé zámky obvykle pořízené na řádcích nebo klíčích nebo kde se obvykle používá jeden zámek tabulky. Ve výchozím nastavení používá režim uzamčení vhodný pro operaci. Pokud jsou zadány v transakcích, které pracují na úrovni izolace SNAPSHOT
, zámky stránek nejsou převzaty, pokud PAGLOCK
není kombinován s dalšími radami tabulky, které vyžadují zámky, jako jsou UPDLOCK
a HOLDLOCK
.
READCOMMITTED
Určuje, že operace čtení splňují pravidla pro úroveň izolace READ COMMITTED
pomocí uzamčení nebo správy verzí řádků. Pokud je možnost databáze READ_COMMITTED_SNAPSHOT
OFF
, databázový stroj získá sdílené zámky, protože data se čtou a po dokončení operace čtení tyto zámky uvolní. Pokud je možnost databáze READ_COMMITTED_SNAPSHOT
ON
, databázový stroj nezíská zámky a používá správu verzí řádků. Další informace o úrovních izolace naleznete v tématu SET TRANSACTION ISOLATION LEVEL.
Poznámka
Pro příkazy UPDATE
nebo DELETE
: Tato funkce se odebere v budoucí verzi SQL Serveru. Nepoužívejte tuto funkci v nové vývojové práci a naplánujte úpravu aplikací, které tuto funkci aktuálně používají.
READCOMMITTEDLOCK
Určuje, že operace čtení splňují pravidla pro úroveň izolace READ COMMITTED
pomocí uzamčení. Databázový stroj získá sdílené zámky při čtení dat a uvolní tyto zámky při dokončení operace čtení bez ohledu na nastavení READ_COMMITTED_SNAPSHOT
databáze. Další informace o úrovních izolace naleznete v tématu SET TRANSACTION ISOLATION LEVEL. Tento tip nelze zadat v cílové tabulce příkazu INSERT
; Vrátí se chyba 4140.
READPAST
Určuje, že databázový stroj nečte řádky, které jsou uzamčeny jinými transakcemi. Po zadání READPAST
se zámky na úrovni řádků přeskočí, ale zámky na úrovni stránky se nepřekočí. To znamená, že databázový stroj přeskočí za řádky místo blokování aktuální transakce, dokud se zámky nevyvolají. Předpokládejme například, že tabulka T1
obsahuje jeden celočíselnou sloupec s hodnotami 1, 2, 3, 4, 5. Pokud transakce A změní hodnotu 3 na 8, ale ještě nebyla potvrzena, SELECT * FROM T1 (READPAST)
zobrazí hodnoty 1, 2, 4, 5.
READPAST
se primárně používá k omezení kolizí uzamčení při implementaci pracovní fronty, která používá tabulku SQL Serveru. Čtenář fronty, který používá READPAST
přeskočí předchozí položky fronty uzamčené jinými transakcemi na další dostupnou položku fronty, aniž by musel čekat, až ostatní transakce uvolní jejich zámky.
READPAST
lze zadat pro libovolnou tabulku odkazovanou v příkazu UPDATE
nebo DELETE
a všechny tabulky odkazované v klauzuli FROM
. Při zadání v příkazu UPDATE
se READPAST
použije pouze při čtení dat k identifikaci záznamů, které se mají aktualizovat, bez ohledu na to, kde je zadaný příkaz.
READPAST
nelze zadat pro tabulky v klauzuli INTO
příkazu INSERT
. Operace aktualizace nebo odstranění, které používají READPAST
mohou blokovat čtení cizích klíčů nebo indexovaných zobrazení nebo při úpravách sekundárních indexů.
READPAST
lze zadat pouze v transakcích, které fungují na úrovni izolace READ COMMITTED
nebo REPEATABLE READ
. Při zadání v transakcích, které pracují na úrovni izolace SNAPSHOT
, musí být READPAST
kombinovány s dalšími radami tabulky, které vyžadují zámky, jako jsou UPDLOCK
a HOLDLOCK
.
Pokud je možnost READ_COMMITTED_SNAPSHOT
databáze nastavená na ON
, není možné zadat nápovědu k tabulce READPAST
a platí některé z následujících podmínek:
- Úroveň izolace transakcí relace je
READ COMMITTED
. - V dotazu je také zadána nápověda k
READCOMMITTED
tabulce.
Chcete-li zadat READPAST
nápovědu v těchto případech, odeberte READCOMMITTED
nápovědu tabulky, pokud je k dispozici, a do dotazu zahrňte nápovědu READCOMMITTEDLOCK
tabulky.
READUNCOMMITTED
Určuje, že jsou povolená zašpiněná čtení. Nejsou vydány žádné sdílené zámky, aby zabránily jiným transakcím v úpravě dat přečtených aktuální transakcí a výhradní zámky nastavené jinými transakcemi nezablokují aktuální transakci čtení uzamčených dat. Povolení nezašpiněných čtení může způsobit vyšší souběžnost, ale za cenu čtení úprav dat, které se pak vrátí zpět jinými transakcemi. To může generovat chyby pro vaši transakci, prezentovat uživatele s daty, která nebyla potvrzena, nebo způsobit, že se záznamy zobrazí dvakrát (nebo vůbec).
READUNCOMMITTED
a nápovědy pro NOLOCK
platí jenom pro zámky dat. Všechny dotazy, včetně dotazů s READUNCOMMITTED
a NOLOCK
nápovědou, získávají během kompilace a provádění zámky Sch-S (stabilita schématu). Z tohoto důvodu jsou dotazy blokovány, když souběžná transakce obsahuje zámek Sch-M (úpravy schématu) v tabulce. Například operace jazyka DDL (Data Definition Language) získá zámek Sch-M předtím, než upraví informace o schématu tabulky. Všechny souběžné dotazy, včetně dotazů spuštěných s READUNCOMMITTED
nebo nápovědou NOLOCK
, se při pokusu o získání zámku Sch-S zablokují. Naopak dotaz, který obsahuje zámek Sch-S blokuje souběžnou transakci, která se pokusí získat Sch-M zámek.
READUNCOMMITTED
a NOLOCK
nelze zadat pro tabulky upravené operacemi vložení, aktualizace nebo odstranění. Optimalizátor dotazů SQL Serveru ignoruje READUNCOMMITTED
a NOLOCK
nápovědy v klauzuli FROM
, které platí pro cílovou tabulku příkazu UPDATE
nebo DELETE
.
Poznámka
Podpora použití READUNCOMMITTED
a NOLOCK
nápovědy v klauzuli FROM
, která platí pro cílovou tabulku příkazu UPDATE
nebo DELETE
, se v budoucí verzi SQL Serveru odebere. Nepoužívejte tyto rady v tomto kontextu v nové vývojové práci a naplánujte úpravu aplikací, které je aktuálně používají.
Kolize uzamčení můžete minimalizovat při ochraně transakcí před nečtenými úpravami nepotvrzených dat pomocí některé z následujících možností:
- Úroveň izolace
READ COMMITTED
s možnostíREAD_COMMITTED_SNAPSHOT
databáze nastavenouON
. - Úroveň izolace
SNAPSHOT
.
Další informace o úrovních izolace naleznete v tématu SET TRANSACTION ISOLATION LEVEL.
Poznámka
Pokud se při zadání READUNCOMMITTED
zobrazí chybová zpráva 601, vyřešte ji tak, jak by se zobrazila chyba zablokování (chybová zpráva 1205) a zkuste příkaz zopakovat.
REPEATABLEREAD
Určuje, že kontrola se provádí se stejnou sémantikou uzamčení jako transakce spuštěná na úrovni izolace REPEATABLE READ
. Další informace o úrovních izolace naleznete v tématu SET TRANSACTION ISOLATION LEVEL.
VESLOVÁ VIDLICE
Určuje, že zámky řádků se pořídí, když se obvykle zamknou zámky stránek nebo tabulek. Pokud jsou zadány v transakcích, které pracují na úrovni izolace SNAPSHOT
, zámky řádků nejsou převzaty, pokud ROWLOCK
není kombinován s dalšími pokyny tabulky, které vyžadují zámky, jako jsou UPDLOCK
a HOLDLOCK
.
ROWLOCK
nelze použít s tabulkou, která má clusterovaný index columnstore. Následující příklad vrátí chybu 651 do aplikace.
UPDATE [dbo].[FactResellerSalesXL_CCI] WITH (ROWLOCK)
SET UnitPrice = 50
WHERE ProductKey = 150;
SERIALIZOVATELNÝ
Ekvivalent HOLDLOCK
. Zneužívá sdílené zámky tím, že je drží, dokud se transakce nedokončí, namísto uvolnění sdíleného zámku, jakmile už není potřebná požadovaná tabulka nebo datová stránka, bez ohledu na to, zda byla transakce dokončena nebo ne. Kontrola se provádí se stejnou sémantikou jako transakce spuštěná na úrovni izolace SERIALIZABLE
. Další informace o úrovních izolace naleznete v tématu SET TRANSACTION ISOLATION LEVEL.
SNÍMEK
platí pro: SQL Server 2014 (12.x) a novější verze
K tabulce optimalizované pro paměť se přistupuje v rámci izolace SNAPSHOT
.
SNAPSHOT
lze použít pouze s tabulkami optimalizovanými pro paměť (ne s tabulkami založenými na disku), jak je vidět v následujícím příkladu. Další informace naleznete v tématu Úvod do Memory-Optimized tabulky.
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>
platí pro: SQL Server 2012 (11.x) a novější verze
Určuje maximální počet buněk, které se mají použít pro tessellating geometrie nebo geografického objektu. <integer_value> je hodnota mezi 1 a 8192.
Tato možnost umožňuje doladit dobu provádění dotazů úpravou kompromisu mezi dobou provádění primárního a sekundárního filtru. Větší číslo zkracuje dobu provádění sekundárního filtru, ale zvyšuje čas filtru primárního spuštění a menší počet snižuje dobu provádění primárního filtru, ale zvyšuje provádění sekundárního filtru. U hustších prostorových dat by mělo vyšší číslo generovat rychlejší dobu provádění tím, že poskytuje lepší aproximaci s primárním filtrem a snižuje dobu provádění sekundárního filtru. U více zhuštěných dat se nižším číslem sníží doba provádění primárního filtru.
Tato možnost funguje pro ruční i automatické tessellace mřížky.
TABLOCK
Určuje, že se získaný zámek použije na úrovni tabulky. Typ zámku, který se získá, závisí na prováděném příkazu. Například příkaz SELECT
může získat sdílený zámek. Zadáním TABLOCK
se sdílený zámek použije na celou tabulku místo na úrovni řádku nebo stránky. Pokud je zadán také HOLDLOCK
, zámek tabulky se uchovává až do konce transakce.
Při importu dat do haldy pomocí příkazu INSERT INTO <target_table> SELECT <columns> FROM <source_table>
můžete povolit minimální protokolování a optimální uzamčení příkazu zadáním TABLOCK
nápovědy pro cílovou tabulku. Kromě toho musí být model obnovení databáze nastaven na jednoduchý nebo hromadně protokolovaný. Tip TABLOCK
také umožňuje paralelní vkládání do indexů hald nebo clusterovaných indexů columnstore. Další informace naleznete v tématu INSERT.
Při použití s OPENROWSET poskytovatele hromadné sady řádků pro import dat do tabulky, TABLOCK
umožňuje více klientům souběžně načítat data do cílové tabulky s optimalizovaným protokolováním a uzamčením. Další informace naleznete v tématu Požadavky pro minimální protokolování v hromadném importu.
TABLOCKX
Určuje, že se v tabulce převezme výhradní zámek.
UPDLOCK
Určuje, že se mají zamknout aktualizace a uchovávat, dokud transakce nebude dokončena.
UPDLOCK
používá zámky aktualizací pro operace čtení pouze na úrovni řádků nebo na úrovni stránky. Pokud se UPDLOCK
zkombinuje s TABLOCK
nebo je zámek na úrovni tabulky převzat z nějakého jiného důvodu, je místo toho pořízen exkluzivní zámek (X).
Při zadání UPDLOCK
se READCOMMITTED
a READCOMMITTEDLOCK
rady na úrovni izolace ignorují. Pokud je například úroveň izolace relace nastavena na SERIALIZABLE
a dotaz určuje (UPDLOCK
, READCOMMITTED
), READCOMMITTED
tip je ignorován a transakce se spouští pomocí úrovně izolace SERIALIZABLE
.
XLOCK
Určuje, že výhradní zámky se mají vzít a uchovávat, dokud transakce nebude dokončena. Pokud je zadána ROWLOCK
, PAGLOCK
nebo TABLOCK
, platí výhradní zámky na odpovídající úroveň členitosti.
Poznámky
Nápovědy k tabulce se ignorují, pokud k tabulce není přístup plánem dotazu. Příčinou může být to, že optimalizátor nevyvolí přístup k tabulce vůbec nebo kvůli tomu, že se k indexované zobrazení přistupuje. V druhém případě může být přístup k indexovanému zobrazení znemožněný pomocí nápovědy k dotazu OPTION (EXPAND VIEWS)
.
Všechny nápovědy k uzamčení se rozšíří do všech tabulek a zobrazení, ke kterým přistupuje plán dotazu, včetně tabulek a zobrazení odkazovaných v zobrazení. SQL Server také provádí odpovídající kontroly konzistence zámků.
Nápovědy k uzamčení ROWLOCK
, UPDLOCK
a XLOCK
, které získávají zámky na úrovni řádků, můžou umístit zámky na klíče indexu, nikoli na skutečné řádky dat. Pokud má například tabulka neclusterovaný index a příkaz SELECT
, který používá nápovědu k uzamčení, zpracovává zakrývající index, zámek se získá na klíč indexu v indexovém indexu, nikoli na řádku dat v základní tabulce.
Pokud tabulka obsahuje počítané sloupce vypočítané výrazy nebo funkcemi, které přistupují ke sloupcům v jiných tabulkách, nebudou se v těchto tabulkách používat rady tabulek a nebudou se šířit. Například NOLOCK
nápovědu k tabulce je určena pro tabulku v dotazu. Tato tabulka obsahuje počítané sloupce vypočítané kombinací výrazů a funkcí, které přistupují ke sloupcům v jiné tabulce. Tabulky odkazované výrazy a funkcemi při přístupu nepoužívají nápovědu k tabulce NOLOCK
.
SQL Server neumožňuje pro každou z následujících skupin v klauzuli FROM
nápovědu pro více tabulek:
- Podrobné rady:
PAGLOCK
,NOLOCK
,READCOMMITTEDLOCK
,ROWLOCK
,TABLOCK
neboTABLOCKX
. - Rady na úrovni izolace:
HOLDLOCK
,NOLOCK
,READCOMMITTED
,REPEATABLEREAD
,SERIALIZABLE
.
Filtrované nápovědy k indexu
Filtrovaný index lze použít jako nápovědu k tabulce, ale způsobí, že optimalizátor dotazů vygeneruje chybu 8622, pokud nepokrývá všechny řádky, které dotaz vybere. Následuje příklad neplatné filtrované nápovědy indexu. Příklad vytvoří filtrovaný index FIBillOfMaterialsWithComponentID
a pak ho použije jako nápovědu indexu pro příkaz SELECT
. Predikát filtrovaného indexu obsahuje řádky dat pro id komponent 533, 324 a 753. Predikát dotazu obsahuje také řádky dat pro identifikátory ComponentID 533, 324 a 753, ale rozšiřuje sadu výsledků tak, aby zahrnovala identifikátory ComponentID 855 a 924, které nejsou ve filtrovaného indexu. Optimalizátor dotazů proto nemůže použít filtrovaný nápovědu indexu a vygeneruje chybu 8622. Další informace najdete v tématu Vytvoření filtrovaných indexů.
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
Optimalizátor dotazů nebere v úvahu nápovědu indexu, pokud možnosti SET
nemají požadované hodnoty pro filtrované indexy. Další informace naleznete v tématu CREATE INDEX.
Použití NOEXPAND
NOEXPAND
platí pouze pro indexovaná zobrazení. Indexované zobrazení je zobrazení s jedinečným clusterovaným indexem vytvořeným na něm. Pokud dotaz obsahuje odkazy na sloupce, které jsou přítomné jak v indexovaných zobrazeních, tak v základních tabulkách, a optimalizátor dotazů určí, že použití indexovaného zobrazení poskytuje nejlepší metodu pro spuštění dotazu, optimalizátor dotazů použije index v zobrazení. Tato funkce se nazývá indexované zobrazení odpovídající. Před SQL Serverem 2016 (13.x) s aktualizací Service Pack 1 je automatické použití indexovaného zobrazení optimalizátorem dotazů podporováno pouze v konkrétních edicích SQL Serveru. V SQL Serveru 2016 (13.x) s aktualizací Service Pack 1 a novějšími verzemi podporují všechny edice automatické použití indexovaného zobrazení. Azure SQL Database a Azure SQL Managed Instance také podporují automatické použití indexovaných zobrazení bez zadání nápovědy NOEXPAND
.
Další informace naleznete v tématu Průvodce architekturou zpracování dotazů.
Seznam funkcí podporovaných edicemi SQL Serveru ve Windows najdete tady:
- Edice a podporované funkce SQL Serveru 2022
- Edice a podporované funkce sql Serveru 2019
- Edice a podporované funkce SQL Serveru 2017
- Edice a podporované funkce SQL Serveru 2016
Aby však optimalizátor dotazů zvážil indexovaná zobrazení pro porovnávání, nebo použít indexované zobrazení, na které odkazuje NOEXPAND
nápověda, musí být následující možnosti SET
nastaveny na ON
.
- ANSI_NULLS
- ANSI_PADDING
- ANSI_WARNINGS
- ARITHABORT 1
- CONCAT_NULL_YIELDS_NULL
- QUOTED_IDENTIFIER
1ARITHABORT
je implicitně nastaven na ON
, když je ANSI_WARNINGS
nastavena na ON
. Proto nemusíte toto nastavení upravovat ručně.
Také musí být možnost NUMERIC_ROUNDABORT
nastavena na OFF
.
Pokud chcete vynutit, aby optimalizátor dotazů používal index pro indexované zobrazení, zadejte možnost NOEXPAND
. Tento tip lze použít pouze v případě, že je zobrazení také pojmenováno v dotazu. SQL Server neposkytuje nápovědu k vynucení použití konkrétního indexovaného zobrazení v dotazu, který nenázví zobrazení přímo v klauzuli FROM
. Optimalizátor dotazů ale považuje použití indexovaných zobrazení, i když na něj přímo v dotazu neodkazuje. Databázový stroj SQL Serveru při použití nápovědy k tabulce NOEXPAND
automaticky vytváří statistiky pouze v indexovaném zobrazení. Vynechání tohoto tipu může vést k upozornění plánu provádění na chybějící statistiky, které nelze vyřešit ručním vytvořením statistiky.
Při optimalizaci dotazů používá databázový stroj statistiku zobrazení, která byla vytvořena automaticky nebo ručně, když dotaz odkazuje přímo na zobrazení a použije se NOEXPAND
nápověda.
Použití nápovědy k tabulce jako nápovědy k dotazu
nápovědy k tabulce lze také zadat jako nápovědu dotazu pomocí klauzule OPTION (TABLE HINT)
. Jako nápovědu k dotazu doporučujeme použít nápovědu tabulky pouze v kontextu průvodce plánem . U ad hoc dotazů zadejte tyto nápovědy pouze jako nápovědy k tabulce. Další informace najdete v tématu nápovědy k dotazům.
Dovolení
Nápovědy pro KEEPIDENTITY
, IGNORE_CONSTRAINTS
a IGNORE_TRIGGERS
vyžadují ALTER
oprávnění k tabulce.
Příklady
A. Určení metody uzamčení pomocí nápovědy TABLOCK
Následující příklad určuje, že sdílený zámek je převzat v tabulce Production.Product
v databázi AdventureWorks2022 a je uložen až do konce příkazu UPDATE
.
UPDATE Production.Product WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO
B. Určení operace hledání indexu pomocí nápovědy FORCESEEK
Následující příklad používá FORCESEEK
nápovědu bez zadání indexu k vynucení optimalizátoru dotazu k provedení operace hledání indexu v tabulce Sales.SalesOrderDetail
v databázi 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
Následující příklad používá FORCESEEK
nápovědu s indexem k vynucení optimalizátoru dotazu k provedení operace hledání indexu u zadaného indexu a indexového sloupce.
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. Určení operace prohledávání indexu pomocí nápovědy FORCESCAN
Následující příklad používá FORCESCAN
nápovědu k vynucení optimalizátoru dotazu k provedení operace prohledávání v tabulce Sales.SalesOrderDetail
v databázi 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);
Související obsah
-
OPENROWSET (Transact-SQL) - rady (Transact-SQL)
-
nápovědy k dotazům (Transact-SQL)