sql >> Database >  >> RDS >> Sqlserver

Op welke kolom moet de geclusterde index worden geplaatst?

Een index, al dan niet geclusterd, kan door de query-optimizer worden gebruikt als en alleen als de meest linkse sleutel in de index is gefilterd. Dus als u een index op kolommen (A, B, C) definieert, een WHERE-voorwaarde op [email protected] , op [email protected] of op [email protected] AND [email protected] zal de index niet volledig benutten (zie opmerking). Dit geldt ook voor de toetredingsvoorwaarden. Elk WHERE-filter dat A . bevat zal rekening houden met de index:[email protected] of [email protected] AND [email protected] of [email protected] AND [email protected] of [email protected] AND [email protected] AND [email protected] .

Dus in jouw voorbeeld als je de geclusterde index maakt op part_no als de meest linkse toets, dan een zoekopdracht op zoek naar een specifieke part_id zal niet gebruik de index en er moet een aparte niet-geclusterde index bestaan ​​op part-id .

Nu over de vraag welke van de vele indexen moet worden geclusterd een. Als u meerdere zoekpatronen heeft die ongeveer even belangrijk en even vaak voorkomen en die elkaar tegenspreken wat betreft de benodigde sleutels (bijv. frequente zoekopdrachten door een van beide part_no of part_id ) dan houdt u rekening met andere factoren:

  • breedte :de geclusterde indexsleutel wordt gebruikt als opzoeksleutel door allen andere niet-geclusterde indexen. Dus als je een brede sleutel kiest (zeg twee uniquidentifier-kolommen), dan maak je alle andere indexen breder, waardoor je meer ruimte in beslag neemt, meer IO genereert en alles vertraagt. Dus tussen even goede sleutels vanuit leesoogpunt, kies de smalste als geclusterd en maak de bredere niet-geclusterd.
  • conflict :als je specifieke patronen voor invoegen en verwijderen hebt, probeer ze dan fysiek te scheiden, zodat ze op verschillende delen van de geclusterde index voorkomen. bijv. als de tabel fungeert als een wachtrij met alle invoegingen aan het ene logische uiteinde en alle verwijderingen aan het andere logische uiteinde, probeer dan de geclusterde index zo in te delen dat de fysieke volgorde overeenkomt met deze logische volgorde (bijv. wachtrijvolgorde).
  • partitioneren :als de tabel erg groot is en u partitionering wilt implementeren, moet de partitiesleutel de geclusterde index zijn. Een typisch voorbeeld zijn historische gegevens die worden gearchiveerd met behulp van een partitioneringsschema met schuifvensters. Ook al hebben de entiteiten een logische primaire sleutel zoals 'entity_id', de geclusterde index wordt gedaan door een datetime-kolom die ook wordt gebruikt voor de partitioneringsfunctie.
  • stabiliteit :een sleutel die vaak verandert, is een slechte kandidaat voor een geclusterde sleutel, aangezien elke de geclusterde sleutelwaarde bijwerkt en alles forceert niet-geclusterde indexen om de opzoeksleutel die ze opslaan bij te werken. Aangezien een update van een geclusterde sleutel het record waarschijnlijk ook naar een andere pagina zal verplaatsen, kan dit fragmentatie op de geclusterde index veroorzaken.

Opmerking:niet volledig hefboomwerking, omdat de engine soms een niet-geclusterde index kiest om te scannen in plaats van de geclusterde index, simpelweg omdat deze smaller is en dus minder pagina's heeft om te scannen. In mijn voorbeeld als je een index hebt op (A, B, C) en een WHERE-filter op [email protected] en de zoekprojecten C , zal de index waarschijnlijk worden gebruikt, maar niet als zoekactie, als scan, omdat deze nog steeds sneller is dan een volledige geclusterde scan (minder pagina's).



  1. SQL Server-isolatieniveaus:een serie

  2. Gebruik sys.trigger_event_types om triggergebeurtenistypen in SQL Server weer te geven

  3. Sql*plus retourneert altijd exit-code 0?

  4. De database-e-mailwachtrij stoppen/starten in SQL Server (T-SQL)