Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
platí pro: SQL Server
Azure SQL Database
Azure SQL Managed Instance
Všechny tabulky optimalizované pro paměť musí mít alespoň jeden index, protože se jedná o indexy, které spojují řádky. V tabulce optimalizované pro paměť je každý index také optimalizován pro paměť. Index v tabulce optimalizované pro paměť se liší od tradičního indexu v tabulce založené na disku několika způsoby:
- Řádky dat nejsou uloženy na stránkách, takže neexistuje žádná kolekce stránek nebo rozsahů, žádné oddíly ani alokační jednotky, na které se dají odkazovat, aby se na všechny stránky tabulky dostaly. Existuje koncept indexových stránek pro jeden z dostupných typů indexů, ale ukládají se odlišně než indexy pro diskové tabulky. Nenačítají tradiční typ fragmentace na stránce, a proto nemají žádný fillfactor.
- Změny indexů v tabulkách optimalizovaných pro paměť během manipulace s daty se nikdy nezapisují na disk. Do transakčního protokolu se zapisují pouze řádky dat a změny dat.
- Indexy optimalizované pro paměť se znovu sestaví, když se databáze vrátí do režimu online.
Všechny indexy v tabulkách optimalizovaných pro paměť se vytvářejí na základě definic indexů během obnovení databáze.
Index musí být jeden z následujících:
- Hašovací index
- Neclusterovaný index optimalizovaný pro paměť (což znamená výchozí interní strukturu stromu B)
Hash indexy jsou diskutovány podrobněji v Hash indexech pro pamětí optimalizované tabulky.
Neclusterované indexy jsou podrobněji popsány v neclusterovaný index pro paměťově optimalizované tabulky.
Indexy columnstore jsou popsány v jiném článku.
Syntaxe indexů optimalizovaných pro paměť
Každý příkaz CREATE TABLE pro tabulku optimalizovanou pro paměť musí obsahovat index, a to buď explicitně prostřednictvím indexu, nebo implicitně prostřednictvím omezení PRIMARY KEY nebo UNIQUE.
Pokud má být deklarována výchozí hodnota DURABILITY = SCHEMA_AND_DATA, paměťově optimalizovaná tabulka musí mít primární klíč. Klauzule PRIMARY KEY NONCLUSTERED v následujícím příkazu CREATE TABLE splňuje dva požadavky:
Poskytuje index, který splňuje minimální požadavek jednoho indexu v příkazu CREATE TABLE.
Poskytuje primární klíč, který je nutný pro klauzuli SCHEMA_AND_DATA.
CREATE TABLE SupportEvent ( SupportEventId int NOT NULL PRIMARY KEY NONCLUSTERED, ... ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
Poznámka:
SQL Server 2014 (12.x) a SQL Server 2016 (13.x) mají limit 8 indexů na tabulku nebo typ tabulky optimalizované pro paměť. Počínaje SQL Serverem 2017 (14.x) a ve službě Azure SQL Database už neexistuje omezení počtu indexů specifických pro tabulky a typy tabulek optimalizovaných pro paměť.
Ukázka kódu pro syntaxi
Tato pododdíl obsahuje blok kódu Transact-SQL, který ukazuje syntaxi pro vytvoření různých indexů v tabulce optimalizované pro paměť. Kód ukazuje následující:
Vytvořte tabulku optimalizovanou pro paměť.
Pomocí příkazů ALTER TABLE přidejte dva indexy.
VLOŽTE několik řádků dat.
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
Duplicitní hodnoty klíče indexu
Duplicitní hodnoty pro klíč indexu můžou snížit výkon tabulek optimalizovaných pro paměť. Systém zpracovává duplikáty při průchodu vstupními řetězci pro většinu operací čtení a zápisu na index. Pokud řetězec duplicitních položek překročí 100 položek, může být snížení výkonu měřitelné.
Duplicitní hash hodnoty
Tento problém je více viditelný v případě indexů hash. Indexy hash trpí více z následujících důvodů:
- Nižší náklady na operaci pro indexy hash.
- Interference velkých duplicitních řetězců s řetězem kolizí hash.
Pokud chcete omezit duplicitu v indexu, vyzkoušejte následující úpravy:
- Použijte neclusterovaný index.
- Přidejte další sloupce na konec indexového klíče, abyste snížili počet duplicit.
- Můžete například přidat sloupce, které jsou také v primárním klíči.
Další informace o kolizích hodnot hash najdete v tématu Indexy hash pro tabulky Memory-Optimized.
Příklad vylepšení
Tady je příklad, jak se vyhnout neefektivitě výkonu indexu.
Vezměte v Customers úvahu tabulku, která má primární klíč na CustomerIda má index ve sloupci CustomerCategoryID. V dané kategorii bude obvykle mnoho zákazníků. Proto bude v daném klíči indexu k dispozici mnoho duplicitních hodnot pro CustomerCategoryID.
V tomto scénáři je osvědčeným postupem použít neclusterovaný index pro (CustomerCategoryID, CustomerId). Tento index lze použít pro dotazy, které používají predikát zahrnující CustomerCategoryID, ale klíč indexu neobsahuje duplikaci. Proto duplicitní hodnoty CustomerCategoryID nebo nadbytečný sloupec v indexu nevedou k neeficienci v údržbě indexu.
Následující dotaz ukazuje průměrný počet duplicitních hodnot klíče indexu pro index CustomerCategoryID v tabulce Sales.Customersv ukázkové databázi WideWorldImporters.
SELECT AVG(row_count) FROM
(SELECT COUNT(*) AS row_count
FROM Sales.Customers
GROUP BY CustomerCategoryID) a
Pokud chcete vyhodnotit průměrný počet duplicit indexového klíče pro vlastní tabulku a index, nahraďte Sales.Customers názvem tabulky a nahraďte CustomerCategoryID seznamem sloupců klíče indexu.
Porovnání, kdy použít každý typ indexu
Povaha konkrétních dotazů určuje, jaký typ indexu je nejlepší volbou.
Při implementaci tabulek optimalizovaných pro paměť v existující aplikaci je obecným doporučením začít s neclusterovanými indexy, protože jejich schopnosti se více podobají možnostem tradičních clusterovaných a neclusterovaných indexů v tabulkách založených na disku.
Doporučení pro použití neclusterovaného indexu
Neclusterovaný index je vhodnější než index hash, pokud:
- Dotazy mají klauzuli
ORDER BYna indexovaném sloupci. - Dotazy, ve kterých se testují pouze počáteční sloupce indexu s více sloupci
- Dotazy testují indexovaný sloupec pomocí
WHEREklauzule s:- Nerovnost:
WHERE StatusCode != 'Done' - Skenování rozsahu hodnot:
WHERE Quantity >= 100
- Nerovnost:
Ve všech následujících příkazech SELECT je neclusterovaný index vhodnější než index hash:
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';
Doporučení pro použití indexu hash
Indexy hash se primárně používají pro vyhledávání bodů a ne pro kontroly rozsahu.
Hashový index je vhodnější než neklastrovaný index, když dotazy používají rovnostní predikáty a klauzule WHERE se mapuje na všechny sloupce klíčů indexu, jak je znázorněno v následujícím příkladu.
SELECT CustomerName
FROM SupportEvent
WHERE SupportEngineerName = 'Liz';
Index s více sloupci
Index s více sloupci může být neclusterovaný index nebo index hash. Předpokládejme, že sloupce indexu jsou col1 a col2. Vzhledem k následujícímu SELECT příkazu by byl pro optimalizátor dotazů užitečný jenom neclusterovaný index:
SELECT col1, col3
FROM MyTable_memop
WHERE col1 = 'dn';
Index hash potřebuje klauzuli WHERE k určení testu rovnosti pro každý z jeho sloupců v klíči. Jinak index hash není pro optimalizátor dotazů užitečný.
Žádný typ indexu není užitečný, pokud WHERE klauzule určuje pouze druhý sloupec v klíči indexu.
Souhrnná tabulka pro porovnání scénářů použití indexu
V následující tabulce jsou uvedeny všechny operace podporované různými typy indexů. Ano znamená, že index může efektivně obsluhovat požadavek a ne znamená, že index nemůže efektivně splnit požadavek.
| Operation | Optimalizováno pro paměť, hodnota hash |
Optimalizováno pro paměť, neklastrovaný |
Založené na disku (bez clusteru) |
|---|---|---|---|
| Prohledávání indexu, načtení všech řádků tabulky | Ano | Ano | Ano |
| Vyhledávání v indexu pro rovnostní predikáty (=). | Ano (Vyžaduje se úplný klíč.) |
Ano | Ano |
| Vyhledávání v indexu pro nerovnosti a predikáty rozsahu (>, <, <=, >=, BETWEEN). |
Ne (Výsledkem je prohledávání indexu.) |
Ano 1 | Ano |
| Získejte řádky v pořadí řazení, které odpovídá definici indexu. | Ne | Ano | Ano |
| Načtěte řádky v pořadí řazení, které odpovídá obrácené definici indexu. | Ne | Ne | Ano |
1 Pro neclusterovaný index optimalizovaný pro paměť není k provedení hledání indexu vyžadován úplný klíč.
Automatická správa indexů a statistik
Využijte řešení, jako je například Adaptivní index Defrag , k automatické správě defragmentace indexů a aktualizací statistik pro jednu nebo více databází. Tento postup automaticky zvolí, zda se má index znovu sestavit nebo změnit uspořádání podle úrovně fragmentace, mimo jiné parametry, a aktualizovat statistiky lineární prahovou hodnotou.
Viz také
Průvodce návrhem indexu SQL Serveru
Hashové indexy pro paměťově optimalizované tabulky
Neclusterované indexy pro pamětí optimalizované tabulky
Adaptivního Indexu Defragmentace