Tabelhints (Transact-SQL)
van toepassing op:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL-database in Microsoft Fabric
Tabelhints worden gebruikt om het standaardgedrag van de queryoptimalisatie te overschrijven tijdens de DML-instructie (Data Manipulat Language). U kunt een vergrendelingsmethode, een of meer indexen, een bewerking voor het verwerken van query's opgeven, zoals een tabelscan of indexzoeken, of andere opties. Tabelhints worden opgegeven in de FROM
component van de DML-instructie en zijn alleen van invloed op de tabel of weergave waarnaar in die component wordt verwezen.
Voorzichtigheid
Omdat de SQL Server-queryoptimalisatie doorgaans het beste uitvoeringsplan voor een query selecteert, raden we u aan om hints alleen te gebruiken als laatste redmiddel door ervaren ontwikkelaars en databasebeheerders.
van toepassing op:
- VERWIJDEREN
- INSERT-
- SELECT-
- UPDATE-
- SAMENVOEGEN
Transact-SQL syntaxisconventies
Syntaxis
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
}
Argumenten
WITH ( <table_hint> ) [ , ] ...n ]
Met sommige uitzonderingen worden tabelhints alleen ondersteund in de FROM
component wanneer de hints worden opgegeven met het WITH
trefwoord. Tabelhints moeten ook worden opgegeven met haakjes.
Belangrijk
Het weglaten van het WITH
trefwoord is een afgeschafte functie: deze functie wordt verwijderd in een toekomstige versie van SQL Server. Vermijd het gebruik van deze functie in nieuwe ontwikkelwerkzaamheden en plan om toepassingen te wijzigen die momenteel gebruikmaken van deze functie.
De volgende tabelhints zijn toegestaan met en zonder het trefwoord WITH
: NOLOCK
, READUNCOMMITTED
, UPDLOCK
, REPEATABLEREAD
, SERIALIZABLE
, READCOMMITTED
, TABLOCK
, TABLOCKX
, PAGLOCK
, ROWLOCK
, NOWAIT
, READPAST
, XLOCK
, SNAPSHOT
en NOEXPAND
. Wanneer deze tabelhints worden opgegeven zonder het WITH
trefwoord, moeten de hints alleen worden opgegeven. Bijvoorbeeld:
FROM t (TABLOCK)
Wanneer de hint is opgegeven met een andere optie, moet de hint worden opgegeven met het WITH
trefwoord:
FROM t WITH (TABLOCK, INDEX(myindex))
U wordt aangeraden komma's te gebruiken tussen tabelhints.
Belangrijk
Het scheiden van hints door spaties in plaats van komma's is een afgeschafte functie: deze functie wordt verwijderd in een toekomstige versie van SQL Server. Vermijd het gebruik van deze functie in nieuwe ontwikkelwerkzaamheden en plan om toepassingen te wijzigen die momenteel gebruikmaken van deze functie.
NOEXPAND
Hiermee geeft u op dat geïndexeerde weergaven niet worden uitgebreid voor toegang tot onderliggende tabellen wanneer de queryoptimalisatie wordt verwerkt door de queryoptimalisatie. De queryoptimalisatie behandelt de weergave als een tabel met geclusterde index.
NOEXPAND
is alleen van toepassing op geïndexeerde weergaven. Zie NOEXPAND-gebruiken voor meer informatie.
INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
De syntaxis van de INDEX()
geeft de namen of id's van een of meer indexen op die door de queryoptimalisatie moeten worden gebruikt wanneer deze de instructie verwerkt. Met de alternatieve INDEX =
syntaxis wordt één indexwaarde opgegeven. Er kan slechts één indexhint per tabel worden opgegeven.
Als er een geclusterde index bestaat, INDEX(0)
een geclusterde indexscan afdingt en INDEX(1)
een geclusterde indexscan afding of zoek. Als er geen geclusterde index bestaat, INDEX(0)
een tabelscan afdrijving en INDEX(1)
wordt geïnterpreteerd als een fout.
Als er meerdere indexen worden gebruikt in één hintlijst, worden de duplicaten genegeerd en worden de rest van de vermelde indexen gebruikt om de rijen van de tabel op te halen. De volgorde van de indexen in de indexhint is aanzienlijk. Een hint voor meerdere indexen dwingt ook index-ANDing af en de queryoptimalisatie past zoveel mogelijk voorwaarden toe op elke index die wordt geopend. Als de verzameling hints geïndexeerde indexen niet alle kolommen bevat waarnaar wordt verwezen door de query, wordt er een ophaalbewerking uitgevoerd om de resterende kolommen op te halen nadat de SQL Server Database Engine alle geïndexeerde kolommen heeft opgehaald.
Notitie
Wanneer een indexhint die naar meerdere indexen verwijst, wordt gebruikt in de feitentabel in een sterdeelname, negeert de optimizer de indexhint en retourneert een waarschuwingsbericht. Index ORing is ook niet toegestaan voor een tabel met een indexhint die is opgegeven.
Het maximum aantal indexen in de tabelhint is 250 niet-geclusterde indexen.
KEEPIDENTITY
Alleen van toepassing in een INSERT
instructie wanneer de optie BULK
wordt gebruikt met OPENROWSET-.
Hiermee geeft u op dat de identiteitswaarde of -waarden in het geïmporteerde gegevensbestand moeten worden gebruikt voor de identiteitskolom. Als KEEPIDENTITY
niet is opgegeven, worden de identiteitswaarden voor deze kolom geverifieerd, maar niet geïmporteerd en wijst de queryoptimalisatie automatisch unieke waarden toe op basis van de seed- en incrementele waarden die zijn opgegeven tijdens het maken van de tabel.
Belangrijk
Als het gegevensbestand geen waarden bevat voor de identiteitskolom in de tabel of weergave en de identiteitskolom niet de laatste kolom in de tabel is, moet u de identiteitskolom overslaan. Zie Een indelingsbestand gebruiken om een gegevensveld (SQL Server)over te slaan voor meer informatie. Als een identiteitskolom is overgeslagen, wijst de queryoptimalisatie automatisch unieke waarden voor de identiteitskolom toe aan de geïmporteerde tabelrijen.
Zie Identiteitswaarden behouden bij het bulksgewijs importeren van gegevens (SQL Server)voor een voorbeeld waarin deze hint wordt gebruikt in een INSERT ... SELECT * FROM OPENROWSET(BULK...)
instructie.
Zie DBCC CHECKIDENTvoor informatie over het controleren van de identiteitswaarde voor een tabel.
KEEPDEFAULTS
Alleen van toepassing in een INSERT
instructie wanneer de optie BULK
wordt gebruikt met OPENROWSET-.
Hiermee geeft u invoeging van de standaardwaarde van een tabelkolom, indien aanwezig, in plaats van NULL
wanneer de gegevensrecord geen waarde voor de kolom bevat.
Zie voor een voorbeeld dat deze hint in een INSERT ... SELECT * FROM OPENROWSET(BULK...)
-instructie gebruikt, Null-waarden of standaardwaarden behouden tijdens het bulksgewijs importeren (SQL Server).
FORCESEEK [ ( <index_value> ( <index_column_name> [ , ...n ] ) ] ]
Hiermee geeft u op dat de queryoptimalisatie alleen een indexzoekbewerking gebruikt als het toegangspad naar de gegevens in de tabel of weergave.
Notitie
Vanaf SQL Server 2008 R2 (10.50.x) Service Pack 1 kunnen ook indexparameters worden opgegeven. In dat geval houdt de queryoptimalisatie alleen rekening met indexzoekbewerkingen via de opgegeven index met ten minste de opgegeven indexkolommen.
index_value
De indexnaam of index-id-waarde. De index-id 0 (heap) kan niet worden opgegeven. Als u de indexnaam of -id wilt retourneren, voert u een query uit op de
sys.indexes
catalogusweergave.index_column_name
De naam van de indexkolom die moet worden opgenomen in de zoekbewerking. Het opgeven van
FORCESEEK
met indexparameters is vergelijkbaar met het gebruik vanFORCESEEK
met eenINDEX
hint. U kunt echter meer controle krijgen over het toegangspad dat door de queryoptimalisatie wordt gebruikt door zowel de index op te geven waarop moet worden gezocht als de indexkolommen die in de zoekbewerking moeten worden overwogen. De optimizer kan indien nodig rekening houden met meer kolommen. Als er bijvoorbeeld een niet-geclusterde index is opgegeven, kan de optimalisatie ervoor kiezen om naast de opgegeven kolommen geclusterde indexsleutelkolommen te gebruiken.
De FORCESEEK
hint kan op de volgende manieren worden opgegeven.
Syntaxis | Voorbeeld | Beschrijving |
---|---|---|
Zonder index of INDEX hint |
FROM dbo.MyTable WITH (FORCESEEK) |
De queryoptimalisatie beschouwt alleen indexzoekbewerkingen om toegang te krijgen tot de tabel of weergave via een relevante index. |
Gecombineerd met een INDEX hint |
FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex)) |
De queryoptimalisatie beschouwt alleen indexzoekbewerkingen om toegang te krijgen tot de tabel of weergave via de opgegeven index. |
Geparameteriseerd door een index en indexkolommen op te geven | FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3))) |
De queryoptimalisatie beschouwt alleen indexzoekbewerkingen om toegang te krijgen tot de tabel of weergave via de opgegeven index met ten minste de opgegeven indexkolommen. |
Houd rekening met de volgende richtlijnen wanneer u de FORCESEEK
hint (met of zonder indexparameters) gebruikt:
- De hint kan worden opgegeven als een tabelhint of als een queryhint. Zie Queryhints (Transact-SQL)voor meer informatie over queryhints.
- Als u
FORCESEEK
wilt toepassen op een geïndexeerde weergave, moet ook deNOEXPAND
hint worden opgegeven. - De hint kan maximaal één keer per tabel of weergave worden toegepast.
- De hint kan niet worden opgegeven voor een externe gegevensbron. Fout 7377 wordt geretourneerd wanneer
FORCESEEK
is opgegeven met een indexhint en fout 8180 wordt geretourneerd wanneerFORCESEEK
wordt gebruikt zonder een indexhint. - Als
FORCESEEK
resulteert in geen plannen worden gevonden, wordt fout 8622 geretourneerd.
Wanneer FORCESEEK
is opgegeven met indexparameters, zijn de volgende richtlijnen en beperkingen van toepassing:
- De hint kan niet worden opgegeven voor een tabel die het doel is van een
INSERT
,UPDATE
ofDELETE
instructie. - De hint kan niet worden opgegeven in combinatie met een
INDEX
hint of een andereFORCESEEK
hint. - Ten minste één kolom moet worden opgegeven en moet de voorloopsleutelkolom zijn.
- Aanvullende indexkolommen kunnen worden opgegeven, maar sleutelkolommen kunnen niet worden overgeslagen. Als de opgegeven index bijvoorbeeld de sleutelkolommen bevat
a
,b
enc
, bevat een geldige syntaxisFORCESEEK (MyIndex (a))
enFORCESEEK (MyIndex (a, b)
. Ongeldige syntaxis bevatFORCESEEK (MyIndex (c))
enFORCESEEK (MyIndex (a, c)
. - De volgorde van kolomnamen die in de hint zijn opgegeven, moet overeenkomen met de volgorde van de kolommen in de index waarnaar wordt verwezen.
- Kolommen die niet in de definitie van de indexsleutel staan, kunnen niet worden opgegeven. In een niet-geclusterde index kunnen bijvoorbeeld alleen de gedefinieerde indexsleutelkolommen worden opgegeven. Gegroepeerde sleutelkolommen die automatisch in de index worden opgenomen, kunnen niet worden opgegeven, maar kunnen worden gebruikt door de optimalisatie.
- Een columnstore-index die is geoptimaliseerd voor xVelocity-geheugen, kan niet worden opgegeven als een indexparameter. Fout 366 wordt geretourneerd.
- Als u de indexdefinitie wijzigt (bijvoorbeeld door kolommen toe te voegen of te verwijderen), moet u mogelijk wijzigingen aanbrengen in de query's die naar die index verwijzen.
- De hint voorkomt dat de optimizer rekening houdt met ruimtelijke of XML-indexen in de tabel.
- De hint kan niet worden opgegeven in combinatie met de
FORCESCAN
hint. - Voor gepartitioneerde indexen kan de partitioneringskolom die door SQL Server wordt toegevoegd, niet worden opgegeven in de hint
FORCESEEK
.
Voorzichtigheid
Als u FORCESEEK
met parameters opgeeft, wordt het aantal plannen beperkt dat door de optimizer meer kan worden overwogen dan wanneer u FORCESEEK
zonder parameters opgeeft. Dit kan ertoe leiden dat er in meer gevallen een Plan cannot be generated
fout optreedt.
FORCESCAN
Van toepassing op: SQL Server 2008 R2 (10.50.x) Service Pack 1 en nieuwere versies
Hiermee geeft u op dat de queryoptimalisatie alleen een indexscanbewerking gebruikt als het toegangspad naar de tabel of weergave waarnaar wordt verwezen. De FORCESCAN
hint kan nuttig zijn voor query's waarin de optimizer het aantal betrokken rijen onderschat en een zoekbewerking kiest in plaats van een scanbewerking. Wanneer dit gebeurt, is de hoeveelheid geheugen die wordt verleend voor de bewerking te klein en worden de queryprestaties beïnvloed.
FORCESCAN
kan worden opgegeven met of zonder INDEX
hint. In combinatie met een indexhint (INDEX = index_name, FORCESCAN
), houdt de queryoptimalisatie alleen rekening met scantoegangspaden via de opgegeven index bij toegang tot de opgegeven tabel.
FORCESCAN
kan worden opgegeven met de indexhint INDEX(0)
om een tabelscanbewerking op de basistabel af te dwingen.
Voor gepartitioneerde tabellen en indexen wordt FORCESCAN
toegepast nadat partities zijn geëlimineerd via evaluatie van querypredicaat. Dit betekent dat de scan alleen wordt toegepast op de resterende partities en niet op de hele tabel.
De FORCESCAN
hint heeft de volgende beperkingen:
- De hint kan niet worden opgegeven voor een tabel die het doel is van een
INSERT
,UPDATE
ofDELETE
instructie. - De hint kan niet worden gebruikt met meer dan één indexhint.
- De hint voorkomt dat de queryoptimalisatie rekening houdt met ruimtelijke of XML-indexen in de tabel.
- De hint kan niet worden opgegeven voor een externe gegevensbron.
- De hint kan niet worden opgegeven in combinatie met de
FORCESEEK
hint.
HOLDLOCK
Gelijk aan SERIALIZABLE
. Zie SERIALIZABLE verderop in dit artikel voor meer informatie.
HOLDLOCK
is alleen van toepassing op de tabel of weergave waarvoor deze is opgegeven, en alleen voor de duur van de transactie die is gedefinieerd door de instructie waarin deze wordt gebruikt.
HOLDLOCK
kan niet worden gebruikt in een SELECT-instructie met de optie FOR BROWSE
.
IGNORE_CONSTRAINTS
Alleen van toepassing in een INSERT
instructie wanneer de optie BULK
wordt gebruikt met OPENROWSET-.
Hiermee geeft u op dat de bulkimportbewerking eventuele beperkingen voor de tabel negeert. Standaard controleert INSERT
unieke beperkingen en controleert u beperkingen en beperkingen voor primaire en refererende sleutels. Wanneer IGNORE_CONSTRAINTS
is opgegeven voor een bulkimportbewerking, moet INSERT
deze beperkingen voor een doeltabel negeren. U kunt UNIQUE
, PRIMARY KEY
of NOT NULL
beperkingen niet uitschakelen.
Mogelijk wilt u CHECK
en FOREIGN KEY
beperkingen uitschakelen als de invoergegevens rijen bevatten die beperkingen schenden. Door de beperkingen voor CHECK
en FOREIGN KEY
uit te schakelen, kunt u de gegevens importeren en vervolgens Transact-SQL instructies gebruiken om de gegevens op te schonen.
Wanneer CHECK
en FOREIGN KEY
beperkingen echter worden genegeerd, wordt elke genegeerde beperking in de tabel gemarkeerd als is_not_trusted
in de sys.check_constraints- of sys.foreign_keys catalogusweergave na de bewerking. Op een bepaald moment moet u de beperkingen voor de hele tabel controleren. Als de tabel niet leeg was vóór de bulkimportbewerking, kunnen de kosten voor het opnieuwvalideren van de beperking groter zijn dan de kosten voor het toepassen van CHECK
en FOREIGN KEY
beperkingen op de incrementele gegevens.
IGNORE_TRIGGERS
Alleen van toepassing in een INSERT
instructie wanneer de optie BULK
wordt gebruikt met OPENROWSET-.
Hiermee geeft u op dat triggers die in de tabel zijn gedefinieerd, worden genegeerd door de bulkimportbewerking. Standaard worden INSERT
triggers toegepast.
Gebruik IGNORE_TRIGGERS
alleen als uw toepassing niet afhankelijk is van triggers en de prestaties maximaliseren belangrijk is.
NOLOCK
Gelijk aan READUNCOMMITTED
. Zie READUNCOMMITTED verderop in dit artikel voor meer informatie.
Notitie
Voor UPDATE
- of DELETE
-instructies: deze functie wordt verwijderd in een toekomstige versie van SQL Server. Vermijd het gebruik van deze functie in nieuwe ontwikkelwerkzaamheden en plan om toepassingen te wijzigen die momenteel gebruikmaken van deze functie.
NOWAIT
Hiermee geeft u de database-engine de opdracht om een bericht te retourneren zodra er een vergrendeling op de tabel is aangetroffen.
NOWAIT
is gelijk aan het opgeven van SET LOCK_TIMEOUT 0
voor een specifieke tabel. De NOWAIT
hint werkt niet wanneer de TABLOCK
hint ook is opgenomen. Als u een query wilt beëindigen zonder te wachten wanneer u de TABLOCK
hint gebruikt, moet u de query vooraf laten gaan door SET LOCK_TIMEOUT 0;
.
PAGLOCK
Hiermee worden paginavergrendelingen gebruikt waarbij afzonderlijke vergrendelingen gewoonlijk worden genomen op rijen of sleutels, of waarbij een enkele tabelvergrendeling gewoonlijk wordt gebruikt. Standaard wordt de vergrendelingsmodus gebruikt die geschikt is voor de bewerking. Wanneer deze zijn opgegeven in transacties die werken op het isolatieniveau van SNAPSHOT
, worden paginavergrendelingen niet gebruikt, tenzij PAGLOCK
wordt gecombineerd met andere tabelhints waarvoor vergrendelingen zijn vereist, zoals UPDLOCK
en HOLDLOCK
.
READCOMMITTED
Hiermee geeft u op dat leesbewerkingen voldoen aan de regels voor het READ COMMITTED
isolatieniveau met behulp van vergrendeling of rijversiebeheer. Als de databaseoptie READ_COMMITTED_SNAPSHOT
is OFF
, verkrijgt de database-engine gedeelde vergrendelingen wanneer gegevens worden gelezen en worden deze vergrendelingen vrijgegeven wanneer de leesbewerking is voltooid. Als de databaseoptie READ_COMMITTED_SNAPSHOT
is ON
, verkrijgt de database-engine geen vergrendelingen en maakt gebruik van rijversiebeheer. Zie SET TRANSACTION ISOLATION LEVELvoor meer informatie over isolatieniveaus.
Notitie
Voor UPDATE
- of DELETE
-instructies: deze functie wordt verwijderd in een toekomstige versie van SQL Server. Vermijd het gebruik van deze functie in nieuwe ontwikkelwerkzaamheden en plan om toepassingen te wijzigen die momenteel gebruikmaken van deze functie.
READCOMMITTEDLOCK
Hiermee geeft u op dat leesbewerkingen voldoen aan de regels voor het READ COMMITTED
isolatieniveau met behulp van vergrendeling. De database-engine verkrijgt gedeelde vergrendelingen wanneer gegevens worden gelezen en publiceert deze vergrendelingen wanneer de leesbewerking is voltooid, ongeacht de instelling van de READ_COMMITTED_SNAPSHOT
-databaseoptie. Zie SET TRANSACTION ISOLATION LEVELvoor meer informatie over isolatieniveaus. Deze hint kan niet worden opgegeven in de doeltabel van een INSERT
instructie; fout 4140 wordt geretourneerd.
READPAST
Hiermee geeft u op dat de database-engine geen rijen leest die zijn vergrendeld door andere transacties. Wanneer READPAST
is opgegeven, worden vergrendelingen op rijniveau overgeslagen, maar worden vergrendelingen op paginaniveau niet overgeslagen. De database-engine slaat dus voorbij de rijen in plaats van de huidige transactie te blokkeren totdat de vergrendelingen worden vrijgegeven. Stel dat tabel T1
één geheel getal bevat met de waarden 1, 2, 3, 4, 5. Als transactie A de waarde van 3 naar 8 wijzigt maar nog niet is doorgevoerd, geeft SELECT * FROM T1 (READPAST)
waarden 1, 2, 4, 5.
READPAST
wordt voornamelijk gebruikt om vergrendelingsconflicten te verminderen bij het implementeren van een werkwachtrij die gebruikmaakt van een SQL Server-tabel. Een wachtrijlezer die gebruikmaakt van READPAST
voorbije wachtrijvermeldingen die door andere transacties zijn vergrendeld, overslaat naar de volgende beschikbare wachtrijvermelding, zonder dat u hoeft te wachten totdat de andere transacties hun vergrendelingen vrijgeven.
READPAST
kan worden opgegeven voor elke tabel waarnaar wordt verwezen in een UPDATE
- of DELETE
-instructie, en elke tabel waarnaar wordt verwezen in een FROM
-component. Wanneer deze is opgegeven in een UPDATE
-instructie, wordt READPAST
alleen toegepast bij het lezen van gegevens om te bepalen welke records moeten worden bijgewerkt, ongeacht waar in de instructie wordt opgegeven.
READPAST
kan niet worden opgegeven voor tabellen in de INTO
component van een INSERT
-instructie. Bewerkingen bijwerken of verwijderen die gebruikmaken van READPAST
mogelijk blokkeren bij het lezen van refererende sleutels of geïndexeerde weergaven of bij het wijzigen van secundaire indexen.
READPAST
kunnen alleen worden opgegeven in transacties die werken op de READ COMMITTED
- of REPEATABLE READ
isolatieniveaus. Wanneer deze zijn opgegeven in transacties die op het isolatieniveau van de SNAPSHOT
worden uitgevoerd, moet READPAST
worden gecombineerd met andere tabelhints waarvoor vergrendelingen zijn vereist, zoals UPDLOCK
en HOLDLOCK
.
De READPAST
tabelhint kan niet worden opgegeven wanneer de READ_COMMITTED_SNAPSHOT
databaseoptie is ingesteld op ON
en aan een van de volgende voorwaarden wordt voldaan:
- Het isolatieniveau van de transactie van de sessie wordt
READ COMMITTED
. - De
READCOMMITTED
tabelhint wordt ook opgegeven in de query.
Als u de READPAST
hint in deze gevallen wilt opgeven, verwijdert u de READCOMMITTED
tabelhint indien aanwezig en neemt u de READCOMMITTEDLOCK
tabelhint op in de query.
READUNCOMMITTED
Hiermee geeft u op dat vuile leesbewerkingen zijn toegestaan. Er worden geen gedeelde vergrendelingen uitgegeven om te voorkomen dat andere transacties gegevens wijzigen die worden gelezen door de huidige transactie, en exclusieve vergrendelingen die door andere transacties zijn ingesteld, blokkeren niet dat de huidige transactie de vergrendelde gegevens leest. Het toestaan van vuile leesbewerkingen kan leiden tot hogere gelijktijdigheid, maar ten koste van het lezen van gegevenswijzigingen die vervolgens worden teruggedraaid door andere transacties. Dit kan fouten genereren voor uw transactie, gebruikers presenteren met gegevens die nooit zijn doorgevoerd of ertoe leiden dat gebruikers records tweemaal (of helemaal niet) zien.
READUNCOMMITTED
en NOLOCK
hints zijn alleen van toepassing op gegevensvergrendelingen. Alle query's, inclusief query's met READUNCOMMITTED
en NOLOCK
hints, verkrijgen Sch-S (schemastabiliteit) vergrendelingen tijdens de compilatie en uitvoering. Daarom worden query's geblokkeerd wanneer een gelijktijdige transactie een Sch-M -vergrendeling (schemawijziging) op de tabel bevat. Een DDL-bewerking (Data Definition Language) verkrijgt bijvoorbeeld een Sch-M-vergrendeling voordat de schemagegevens van de tabel worden gewijzigd. Eventuele gelijktijdige query's, waaronder query's die worden uitgevoerd met READUNCOMMITTED
of NOLOCK
hints, worden geblokkeerd bij het verkrijgen van een Sch-S-vergrendeling. Omgekeerd blokkeert een query met een Sch-S-vergrendeling een gelijktijdige transactie die probeert een Sch-M-vergrendeling te verkrijgen.
READUNCOMMITTED
en NOLOCK
kunnen niet worden opgegeven voor tabellen die zijn gewijzigd door invoeg-, update- of verwijderbewerkingen. De sql Server-queryoptimalisatie negeert de READUNCOMMITTED
en NOLOCK
hints in de FROM
component die van toepassing zijn op de doeltabel van een UPDATE
- of DELETE
-instructie.
Notitie
Ondersteuning voor het gebruik van de READUNCOMMITTED
- en NOLOCK
hints in de FROM
-component die van toepassing zijn op de doeltabel van een UPDATE
- of DELETE
-instructie, wordt verwijderd in een toekomstige versie van SQL Server. Vermijd het gebruik van deze hints in deze context in nieuwe ontwikkelwerkzaamheden en plan om toepassingen te wijzigen die deze momenteel gebruiken.
U kunt vergrendelingsconflicten minimaliseren terwijl u transacties beveiligt tegen vuile leesbewerkingen van niet-doorgevoerde gegevenswijzigingen met behulp van een van de volgende opties:
- Het
READ COMMITTED
isolatieniveau met deREAD_COMMITTED_SNAPSHOT
databaseoptieON
ingesteld. - Het
SNAPSHOT
isolatieniveau.
Zie SET TRANSACTION ISOLATION LEVELvoor meer informatie over isolatieniveaus.
Notitie
Als u foutbericht 601 krijgt wanneer READUNCOMMITTED
is opgegeven, kunt u dit oplossen als een impassefout (foutbericht 1205) en voert u de instructie opnieuw uit.
HERHAALBAAR GELEZEN
Hiermee geeft u op dat een scan wordt uitgevoerd met dezelfde vergrendelingssemantiek als een transactie die wordt uitgevoerd op REPEATABLE READ
isolatieniveau. Zie SET TRANSACTION ISOLATION LEVELvoor meer informatie over isolatieniveaus.
ROWLOCK
Hiermee geeft u op dat rijvergrendelingen worden genomen wanneer pagina- of tabelvergrendelingen gewoonlijk worden genomen. Wanneer deze zijn opgegeven in transacties die op het isolatieniveau SNAPSHOT
, worden rijvergrendelingen niet gebruikt, tenzij ROWLOCK
wordt gecombineerd met andere tabelhints waarvoor vergrendelingen zijn vereist, zoals UPDLOCK
en HOLDLOCK
.
ROWLOCK
kan niet worden gebruikt met een tabel met een geclusterde columnstore-index. In het volgende voorbeeld wordt fout 651 geretourneerd naar de toepassing.
UPDATE [dbo].[FactResellerSalesXL_CCI] WITH (ROWLOCK)
SET UnitPrice = 50
WHERE ProductKey = 150;
SERIALIZABLE
Gelijk aan HOLDLOCK
. Hiermee worden gedeelde vergrendelingen beperkter door ze vast te houden totdat een transactie is voltooid, in plaats van de gedeelde vergrendeling vrij te geven zodra de vereiste tabel of gegevenspagina niet meer nodig is, ongeacht of de transactie is voltooid of niet. De scan wordt uitgevoerd met dezelfde semantiek als een transactie die wordt uitgevoerd op het SERIALIZABLE
isolatieniveau. Zie SET TRANSACTION ISOLATION LEVELvoor meer informatie over isolatieniveaus.
MOMENTOPNAME
Van toepassing op: SQL Server 2014 (12.x) en latere versies
De tabel die is geoptimaliseerd voor geheugen is toegankelijk onder SNAPSHOT
isolatie.
SNAPSHOT
kan alleen worden gebruikt met tabellen die zijn geoptimaliseerd voor geheugen (niet met tabellen op basis van schijven), zoals te zien is in het volgende voorbeeld. Zie Inleiding tot Memory-Optimized tabellenvoor meer informatie.
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>
Van toepassing op: SQL Server 2012 (11.x) en latere versies
Hiermee geeft u het maximum aantal cellen op dat moet worden gebruikt om een geometrie- of geografieobject tesselen. <integer_value> is een waarde tussen 1 en 8192.
Met deze optie kunt u de uitvoeringstijd van query's verfijnen door de balans tussen de uitvoeringstijd van het primaire en secundaire filter aan te passen. Een groter aantal vermindert de uitvoeringstijd van secundaire filters, maar verhoogt de primaire uitvoeringstijd van het uitvoeringsfilter en een kleiner aantal vermindert de uitvoeringstijd van het primaire filter, maar verhoogt de uitvoering van secundaire filters. Voor compactere ruimtelijke gegevens moet een hoger getal een snellere uitvoeringstijd produceren door een betere benadering te geven met het primaire filter en de secundaire uitvoeringstijd van het filter te verminderen. Voor meer parseringsgegevens vermindert een lager getal de uitvoeringstijd van het primaire filter.
Deze optie werkt zowel voor handmatige als automatische rasterbesturingselementen.
TABLOCK
Hiermee geeft u op dat de verkregen vergrendeling wordt toegepast op tabelniveau. Het type vergrendeling dat wordt verkregen, is afhankelijk van de instructie die wordt uitgevoerd. Een SELECT
-instructie kan bijvoorbeeld een gedeelde vergrendeling verkrijgen. Door TABLOCK
op te geven, wordt de gedeelde vergrendeling toegepast op de hele tabel in plaats van op rij- of paginaniveau. Als HOLDLOCK
ook is opgegeven, wordt de tabelvergrendeling bewaard tot het einde van de transactie.
Wanneer u gegevens in een heap importeert met behulp van de instructie INSERT INTO <target_table> SELECT <columns> FROM <source_table>
, kunt u minimale logboekregistratie en optimale vergrendeling voor de instructie inschakelen door de TABLOCK
hint voor de doeltabel op te geven. Daarnaast moet het herstelmodel van de database worden ingesteld op eenvoudig of bulksgewijs vastgelegd. De TABLOCK
hint maakt ook parallelle invoegingen mogelijk voor heaps of geclusterde columnstore-indexen. Zie INSERTvoor meer informatie.
Wanneer deze worden gebruikt met de OPENROWSET-provider bulksgewijs rijensetprovider om gegevens in een tabel te importeren, TABLOCK
kunnen meerdere clients gelijktijdig gegevens in de doeltabel laden met geoptimaliseerde logboekregistratie en vergrendeling. Zie Vereisten voor minimale logboekregistratie in bulkimportvoor meer informatie.
TABLOCKX
Hiermee geeft u op dat een exclusieve vergrendeling op de tafel wordt genomen.
UPDLOCK
Hiermee geeft u op dat updatevergrendelingen moeten worden genomen en bewaard totdat de transactie is voltooid.
UPDLOCK
gebruikt updatevergrendelingen alleen voor leesbewerkingen op rij- of paginaniveau. Als UPDLOCK
wordt gecombineerd met TABLOCK
of als een vergrendeling op tabelniveau om een andere reden wordt genomen, wordt in plaats daarvan een exclusieve (X)-vergrendeling genomen.
Wanneer UPDLOCK
is opgegeven, worden de hints READCOMMITTED
en READCOMMITTEDLOCK
isolatieniveau genegeerd. Als het isolatieniveau van de sessie bijvoorbeeld is ingesteld op SERIALIZABLE
en een query (UPDLOCK
, READCOMMITTED
), wordt de READCOMMITTED
hint genegeerd en wordt de transactie uitgevoerd met behulp van het SERIALIZABLE
isolatieniveau.
XLOCK
Hiermee geeft u op dat exclusieve vergrendelingen moeten worden genomen en bewaard totdat de transactie is voltooid. Indien opgegeven met ROWLOCK
, PAGLOCK
of TABLOCK
, zijn de exclusieve vergrendelingen van toepassing op het juiste granulariteitsniveau.
Opmerkingen
De tabelhints worden genegeerd als de tabel niet wordt geopend door het queryplan. Dit kan worden veroorzaakt doordat de optimizer ervoor kiest om helemaal geen toegang te krijgen tot de tabel, of omdat in plaats daarvan een geïndexeerde weergave wordt geopend. In het laatste geval kan het openen van een geïndexeerde weergave worden voorkomen met behulp van de OPTION (EXPAND VIEWS)
queryhint.
Alle vergrendelingshints worden doorgegeven aan alle tabellen en weergaven die worden geopend door het queryplan, inclusief tabellen en weergaven waarnaar wordt verwezen in een weergave. Sql Server voert ook de bijbehorende consistentiecontroles voor vergrendelingen uit.
Vergrendelingshints ROWLOCK
, UPDLOCK
en XLOCK
die vergrendelingen op rijniveau verkrijgen, kunnen vergrendelingen op indexsleutels plaatsen in plaats van de werkelijke gegevensrijen. Als een tabel bijvoorbeeld een niet-geclusterde index heeft en een SELECT
instructie met behulp van een vergrendelingshint wordt verwerkt door een dekkingsindex, wordt een vergrendeling verkregen op de indexsleutel in de betreffende index in plaats van op de gegevensrij in de basistabel.
Als een tabel berekende kolommen bevat die worden berekend door expressies of functies die toegang hebben tot kolommen in andere tabellen, worden de tabelhints niet gebruikt voor deze tabellen en worden ze niet doorgegeven. Er wordt bijvoorbeeld een NOLOCK
tabelhint opgegeven in een tabel in de query. Deze tabel heeft berekende kolommen die worden berekend door een combinatie van expressies en functies die toegang hebben tot kolommen in een andere tabel. De tabellen waarnaar wordt verwezen door de expressies en functies, gebruiken de NOLOCK
tabelhint niet wanneer ze worden geopend.
SQL Server staat niet meer dan één tabelhint toe van elk van de volgende groepen voor elke tabel in de FROM
-component:
- Granulariteitshints:
PAGLOCK
,NOLOCK
,READCOMMITTEDLOCK
,ROWLOCK
,TABLOCK
ofTABLOCKX
. - Hints voor isolatieniveau:
HOLDLOCK
,NOLOCK
,READCOMMITTED
,REPEATABLEREAD
,SERIALIZABLE
.
Gefilterde indexhints
Een gefilterde index kan worden gebruikt als een tabelhint, maar zorgt ervoor dat de queryoptimalisatie fout 8622 genereert als deze niet alle rijen omvat die door de query worden geselecteerd. Hier volgt een voorbeeld van een ongeldige gefilterde indexhint. In het voorbeeld wordt de gefilterde index gemaakt FIBillOfMaterialsWithComponentID
en wordt deze vervolgens gebruikt als indexhint voor een SELECT
-instructie. Het gefilterde indexpredicaat bevat gegevensrijen voor ComponentIDs 533, 324 en 753. Het querypredicaat bevat ook gegevensrijen voor ComponentIDs 533, 324 en 753, maar breidt de resultatenset uit met ComponentID's 855 en 924, die zich niet in de gefilterde index bevinden. Daarom kan de optimalisatiefunctie voor query's de gefilterde indexhint niet gebruiken en fout 8622 genereren. Zie Gefilterde indexen makenvoor meer informatie.
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
De optimalisatiefunctie voor query's beschouwt geen indexhint als de SET
-opties niet over de vereiste waarden beschikken voor gefilterde indexen. Zie CREATE INDEXvoor meer informatie.
NOEXPAND gebruiken
NOEXPAND
geldt alleen voor geïndexeerde weergaven. Een geïndexeerde weergave is een weergave met een unieke geclusterde index die erop is gemaakt. Als een query verwijzingen bevat naar kolommen die zowel aanwezig zijn in een geïndexeerde weergave als basistabellen, en de queryoptimalisatie bepaalt dat het gebruik van de geïndexeerde weergave de beste methode biedt voor het uitvoeren van de query, gebruikt de queryoptimalisatie de index in de weergave. Deze functionaliteit wordt geïndexeerde weergave genoemd die overeenkomt met. Vóór SQL Server 2016 (13.x) met Service Pack 1 wordt automatisch gebruik van een geïndexeerde weergave door de queryoptimalisatie alleen ondersteund in specifieke edities van SQL Server. In SQL Server 2016 (13.x) met Service Pack 1 en latere versies ondersteunen alle edities het automatisch gebruik van een geïndexeerde weergave. Azure SQL Database en Azure SQL Managed Instance ondersteunen ook het automatisch gebruik van geïndexeerde weergaven zonder de NOEXPAND
hint op te geven.
Zie architectuurhandleiding voor queryverwerkingvoor meer informatie.
Zie voor een lijst met functies die worden ondersteund door de edities van SQL Server in Windows:
- Edities en ondersteunde functies van SQL Server 2022
- Edities en ondersteunde functies van SQL Server 2019
- Edities en ondersteunde functies van SQL Server 2017
- Edities en ondersteunde functies van SQL Server 2016
Voor het optimaliseren van query's moet echter rekening worden gehouden met geïndexeerde weergaven voor overeenkomende weergaven of een geïndexeerde weergave gebruiken waarnaar wordt verwezen met de NOEXPAND
hint, moeten de volgende SET
opties worden ingesteld op ON
.
- ANSI_NULLS
- ANSI_PADDING
- ANSI_WARNINGS
- ARITHABORT 1
- CONCAT_NULL_YIELDS_NULL
- QUOTED_IDENTIFIER
1ARITHABORT
wordt impliciet ingesteld op ON
wanneer ANSI_WARNINGS
is ingesteld op ON
. Daarom hoeft u deze instelling niet handmatig aan te passen.
De optie NUMERIC_ROUNDABORT
moet ook worden ingesteld op OFF
.
Als u wilt afdwingen dat de queryoptimalisatie een index gebruikt voor een geïndexeerde weergave, geeft u de optie NOEXPAND
op. Deze hint kan alleen worden gebruikt als de weergave ook een naam heeft in de query. SQL Server biedt geen hint om te forceren dat een bepaalde geïndexeerde weergave wordt gebruikt in een query die de weergave niet rechtstreeks in de FROM
-component een naam geeft. De queryoptimalisatie houdt echter rekening met het gebruik van geïndexeerde weergaven, zelfs als er niet rechtstreeks naar wordt verwezen in de query. De SQL Server Database Engine maakt alleen automatisch statistieken voor een geïndexeerde weergave wanneer een hint voor een NOEXPAND
tabel wordt gebruikt. Als u deze hint weglaat, kan dit leiden tot waarschuwingen voor het uitvoeringsplan over ontbrekende statistieken die niet kunnen worden opgelost door handmatig statistieken te maken.
Tijdens het optimaliseren van query's gebruikt de database-engine weergavestatistieken die automatisch of handmatig zijn gemaakt wanneer de query rechtstreeks naar de weergave verwijst en de NOEXPAND
hint wordt gebruikt.
Een tabelhint gebruiken als een queryhint
tabelhints kunnen ook worden opgegeven als een queryhint met behulp van de OPTION (TABLE HINT)
-component. We raden u aan om een tabelhint alleen te gebruiken als een queryhint in de context van een planhandleiding. Geef voor ad-hocquery's deze hints alleen op als tabelhints. Zie queryhintsvoor meer informatie.
Machtigingen
Voor de KEEPIDENTITY
, IGNORE_CONSTRAINTS
en IGNORE_TRIGGERS
hints zijn ALTER
machtigingen voor de tabel vereist.
Voorbeelden
Een. De TABLOCK-hint gebruiken om een vergrendelingsmethode op te geven
In het volgende voorbeeld wordt aangegeven dat een gedeelde vergrendeling wordt uitgevoerd op de Production.Product
tabel in de Database AdventureWorks2022 en wordt bewaard tot het einde van de instructie UPDATE
.
UPDATE Production.Product WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO
B. De HINT FORCESEEK gebruiken om een indexzoekbewerking op te geven
In het volgende voorbeeld wordt de FORCESEEK
hint gebruikt zonder een index op te geven om de queryoptimalisatie te dwingen een indexzoekbewerking uit te voeren op de Sales.SalesOrderDetail
tabel in de AdventureWorks2022-database.
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
In het volgende voorbeeld wordt de FORCESEEK
hint met een index gebruikt om de queryoptimalisatie te forceren om een indexzoekbewerking uit te voeren op de opgegeven index- en indexkolom.
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. Gebruik de hint FORCESCAN om een indexscanbewerking op te geven
In het volgende voorbeeld wordt de FORCESCAN
hint gebruikt om de queryoptimalisatie te dwingen een scanbewerking uit te voeren op de Sales.SalesOrderDetail
tabel in de Database 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);