Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
gäller för:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Alla minnesoptimerade tabeller måste ha minst ett index, eftersom det är indexen som kopplar ihop raderna. I en minnesoptimerad tabell är varje index också minnesoptimerad. Det finns flera sätt på vilka ett index i en minnesoptimerad tabell skiljer sig från ett traditionellt index i en diskbastabell:
- Datarader lagras inte på sidor, så det finns ingen samling sidor eller omfattningar, inga partitioner eller allokeringsenheter som kan refereras till för att hämta alla sidor för en tabell. Det finns begreppet indexsidor för en av de tillgängliga typerna av index, men de lagras på ett annat sätt än index för diskbaserade tabeller. De ackumulerar inte den traditionella typen av fragmentering på en sida, så de har ingen fillfactor.
- Ändringar som görs i index i minnesoptimerade tabeller under datamanipulering skrivs aldrig till disk. Endast dataraderna och ändringarna av data skrivs till transaktionsloggen.
- Minnesoptimerade index återskapas när databasen är online igen.
Alla index i minnesoptimerade tabeller skapas baserat på indexdefinitionerna under databasåterställningen.
Indexet måste vara något av följande:
- Hash-index
- Minnesoptimerade ickeklustrerat index (vilket innebär den interna standardstrukturen för ett B-träd)
Hash-index beskrivs mer detaljerat i Hash-index för minnesoptimerade tabeller.
Icke-grupperade index beskrivs mer detaljerat i Icke-grupperat index för Memory-Optimized tabeller.
Kolumnlagringsindex diskuteras i en annan artikel.
Syntax för minnesoptimerade index
Varje CREATE TABLE-instruktion för en minnesoptimerad tabell måste innehålla ett index, antingen explicit via ett INDEX eller implicit via en PRIMÄRNYCKEL eller UNIK-begränsning.
För att deklareras med standardvärdet HÅLLBARHET = SCHEMA_AND_DATA måste den minnesoptimerade tabellen ha en primärnyckel. I den följande CREATE TABLE-instruktionen uppfyller PRIMÄR NYCKEL NONCLUSTERED-satsen två krav:
Tillhandahåller ett index för att uppfylla minimikravet för ett index i CREATE TABLE-instruktionen.
Innehåller den primära nyckel som krävs för SCHEMA_AND_DATA-satsen.
CREATE TABLE SupportEvent ( SupportEventId int NOT NULL PRIMARY KEY NONCLUSTERED, ... ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
Anmärkning
SQL Server 2014 (12.x) och SQL Server 2016 (13.x) har en gräns på 8 index per minnesoptimerad tabell eller tabelltyp. Från och med SQL Server 2017 (14.x) och i Azure SQL Database finns det inte längre någon gräns för antalet index som är specifika för minnesoptimerade tabeller och tabelltyper.
Kodexempel för syntax
Det här underavsnittet innehåller ett Transact-SQL kodblock som visar syntaxen för att skapa olika index i en minnesoptimerad tabell. Koden visar följande:
Skapa en minnesoptimerad tabell.
Använd ALTER TABLE-instruktioner för att lägga till två index.
INFOGA några rader med data.
DROP TABLE IF EXISTS SupportEvent; go CREATE TABLE SupportEvent ( SupportEventId int not null identity(1,1) PRIMARY KEY NONCLUSTERED, StartDateTime datetime2 not null, CustomerName nvarchar(16) not null, SupportEngineerName nvarchar(16) null, Priority int null, Description nvarchar(64) null ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA); go -------------------- ALTER TABLE SupportEvent ADD CONSTRAINT constraintUnique_SDT_CN UNIQUE NONCLUSTERED (StartDateTime DESC, CustomerName); go ALTER TABLE SupportEvent ADD INDEX idx_hash_SupportEngineerName HASH (SupportEngineerName) WITH (BUCKET_COUNT = 64); -- Nonunique. go -------------------- INSERT INTO SupportEvent (StartDateTime, CustomerName, SupportEngineerName, Priority, Description) VALUES ('2016-02-23 13:40:41:123', 'Abby', 'Zeke', 2, 'Display problem.' ), ('2016-02-24 13:40:41:323', 'Ben' , null , 1, 'Cannot find help.' ), ('2016-02-25 13:40:41:523', 'Carl', 'Liz' , 2, 'Button is gray.' ), ('2016-02-26 13:40:41:723', 'Dave', 'Zeke', 2, 'Cannot unhide column.'); go
Duplicera indexnyckelvärden
Dubblettvärden för en indexnyckel kan minska prestandan för minnesoptimerade tabeller. Dubbletter gör det möjligt för systemet att gå igenom inmatningskedjor vid de flesta indexläsnings- och skrivoperationer. När en kedja med duplicerade poster överskrider 100 poster kan prestandaförsämringen bli mätbar.
Duplicerade hash-värden
Det här problemet är mer synligt när det gäller hash-index. Hash-index drabbas mer på grund av följande överväganden:
- Den lägre kostnaden per operation för hashindex.
- Interferensen hos stora dubbletter av kedjor med hashkollisionskedjan.
Prova följande justeringar för att minska dupliceringen i ett index:
- Använd ett icke-grupperat index.
- Lägg till ytterligare kolumner i slutet av indexnyckeln för att minska antalet dubbletter.
- Du kan till exempel lägga till kolumner som också finns i primärnyckeln.
Mer information om hash-kollisioner finns i Hash-index för Memory-Optimized tabeller.
Exempel på förbättring
Här är ett exempel på hur du undviker prestanda ineffektivitet i ditt index.
Överväg en Customers tabell som har en primärnyckel på CustomerIdoch som har ett index för kolumnen CustomerCategoryID. Vanligtvis finns det många kunder i en viss kategori. Det kommer därför att finnas många duplicerade värden för CustomerCategoryID i en viss nyckel i indexet.
I det här scenariot är bästa praxis att använda ett icke-klustrat index på (CustomerCategoryID, CustomerId). Det här indexet kan användas för frågor som använder ett predikat med CustomerCategoryID, men indexnyckeln innehåller inte duplicering. Därför orsakas inga ineffektiviteter i indexunderhållet av antingen de duplicerade CustomerCategoryID-värdena eller av den extra kolumnen i indexet.
Följande fråga visar det genomsnittliga antalet duplicerade indexnyckelvärden för indexet CustomerCategoryID i tabellen Sales.Customers, i exempeldatabasen WideWorldImporters.
SELECT AVG(row_count) FROM
(SELECT COUNT(*) AS row_count
FROM Sales.Customers
GROUP BY CustomerCategoryID) a
Om du vill utvärdera det genomsnittliga antalet indexnyckeldubbletter för din egen tabell och ditt eget index ersätter Sales.Customers du med tabellnamnet och ersätter CustomerCategoryID med listan med indexnyckelkolumner.
Jämföra när du ska använda varje indextyp
Typen av specifika frågor avgör vilken typ av index som är det bästa valet.
När du implementerar minnesoptimerade tabeller i en befintlig applikation är den allmänna rekommendationen att börja med icke-klustrade index, eftersom deras funktioner liknar funktionerna i traditionella klustrade och icke-klustrade index på diskbaserade tabeller.
Rekommendationer för icke-grupperad indexanvändning
Ett icke-grupperat index är att föredra framför ett hash-index när:
- Frågor har en
ORDER BYsats i den indexerade kolumnen. - Frågor där endast de inledande kolumnerna i ett flerkolumnsindex testas.
- Fråga testar den indexerade kolumnen med hjälp av en
WHEREklausul med:- En ojämlikhet:
WHERE StatusCode != 'Done' - En värdeintervallsgenomsökning:
WHERE Quantity >= 100
- En ojämlikhet:
I alla följande SELECT:ar är ett icke-grupperat index att föredra framför ett hash-index:
SELECT CustomerName, Priority, Description
FROM SupportEvent
WHERE StartDateTime > DateAdd(day, -7, GetUtcDate());
SELECT StartDateTime, CustomerName
FROM SupportEvent
ORDER BY StartDateTime DESC; -- ASC would cause a scan.
SELECT CustomerName
FROM SupportEvent
WHERE StartDateTime = '2016-02-26';
Rekommendationer för användning av hashindex
Hash-index används främst för punktsökningar och inte för intervallgenomsökningar.
Ett hash-index är att föredra framför ett icke-grupperat index när frågor använder likhetspredikat och WHERE satsen mappar till alla indexnyckelkolumner, som i följande exempel:
SELECT CustomerName
FROM SupportEvent
WHERE SupportEngineerName = 'Liz';
Index med flera kolumner
Ett flerkolumnsindex kan vara ett icke-grupperat index eller ett hash-index. Anta att indexkolumnerna är col1 och col2. Med följande SELECT utsaga skulle endast det icke-klustrade indexet vara användbart för frågeoptimeraren:
SELECT col1, col3
FROM MyTable_memop
WHERE col1 = 'dn';
Hash-indexet behöver klausulen WHERE för att ange ett likhetstest för var och en av kolumnerna i dess nyckel. Annars är hash-indexet inte användbart för frågeoptimeraren.
Ingen av indextyperna WHERE är användbara om satsen endast anger den andra kolumnen i indexnyckeln.
Sammanfattningstabell för att jämföra scenarier för indexanvändning
I följande tabell visas alla åtgärder som stöds av de olika indextyperna. Ja innebär att indexet effektivt kan hantera begäran och Nej innebär att indexet inte effektivt kan uppfylla begäran.
| Verksamhet | Minnesoptimerad, hasch |
Minnesoptimerad, icke-klustrad |
Diskbaserad, (icke)klustrad |
|---|---|---|---|
| Indexgenomsökning, hämta alla tabellrader. | Yes | Yes | Yes |
| Indexsökning på likhetspredikat (=). | Ja (Fullständig nyckel krävs.) |
Yes | Yes |
| Indexsökning på ojämlikhet och intervallpredikat (>, <, <=, >=, BETWEEN). |
Nej (Resulterar i en indexgenomsökning.) |
Ja 1 | Yes |
| Hämta rader i sorteringsordning som matchar indexdefinitionen. | Nej | Yes | Yes |
| Hämta rader i sorteringsordning som matchar indexdefinitionens omvända ordning. | Nej | Nej | Yes |
1 För ett minnesoptimerad icke-grupperat index krävs inte den fullständiga nyckeln för att utföra en indexsökning.
Automatisk index- och statistikhantering
Använd lösningar som Adaptive Index Defrag för att automatiskt hantera indexdefragmentering och statistikuppdateringar för en eller flera databaser. Den här proceduren väljer automatiskt om du vill återskapa eller omorganisera ett index enligt dess fragmenteringsnivå, bland andra parametrar, och uppdatera statistik med ett linjärt tröskelvärde.
Se även
Designguide för SQL Server-index
Hash-indexar för minnesoptimerade tabeller
Icke-grupperade index för Memory-Optimized-tabeller
Defragmentera adaptivt index