sql >> Database >  >> RDS >> Sqlserver

Verbeter de prestaties van SQL Server-query's op grote tabellen

Simpel antwoord:NEE. U kunt niet helpen ad-hocquery's op een tabel met 238 kolommen met een vulfactor van 50% op de geclusterde index.

Gedetailleerd antwoord:

Zoals ik in andere antwoorden over dit onderwerp heb aangegeven, is indexontwerp zowel kunst als wetenschap en zijn er zoveel factoren waarmee rekening moet worden gehouden dat er weinig of geen vaste regels zijn. U moet rekening houden met:het volume van DML-bewerkingen versus SELECT's, schijfsubsysteem, andere indexen / triggers op de tafel, distributie van gegevens binnen de tabel, query's met SARGable WHERE-voorwaarden en verschillende andere dingen die ik me niet eens goed kan herinneren nu.

Ik kan zeggen dat er geen hulp kan worden geboden voor vragen over dit onderwerp zonder begrip van de tabel zelf, zijn indexen, triggers, enz. Nu u de tabeldefinitie hebt gepost (nog steeds wachtend op de indexen, maar de tabeldefinitie alleen wijst naar 99% van het probleem) Ik kan enkele suggesties doen.

Ten eerste, als de tabeldefinitie correct is (238 kolommen, 50% Fill Factor), dan kun je de rest van de antwoorden / adviezen hier vrijwel negeren;-). Sorry dat ik hier minder dan politiek ben, maar serieus, het is een wilde gansjacht zonder de details te kennen. En nu we de tabeldefinitie zien, wordt het een stuk duidelijker waarom een ​​eenvoudige query zo lang zou duren, zelfs als de testquery's (update #1) zo snel liepen.

Het grootste probleem hier (en in veel situaties met slechte prestaties) is slechte gegevensmodellering. 238 kolommen is niet verboden, net zoals het hebben van 999 indexen niet verboden is, maar het is over het algemeen ook niet erg verstandig.

Aanbevelingen:

  1. Eerst moet deze tafel echt opnieuw worden gemodelleerd. Als dit een datawarehouse-tabel is, dan misschien, maar zo niet, dan moeten deze velden echt worden opgedeeld in verschillende tabellen die allemaal dezelfde PK kunnen hebben. U zou een hoofdrecordtabel hebben en de onderliggende tabellen zijn slechts afhankelijke informatie op basis van algemeen geassocieerde attributen en de PK van die tabellen is hetzelfde als de PK van de hoofdtabel en dus ook FK naar de hoofdtabel. Er zal een 1-op-1 relatie zijn tussen hoofd- en alle onderliggende tabellen.
  2. Het gebruik van ANSI_PADDING OFF is verontrustend, om nog maar te zwijgen van inconsistentie in de tabel vanwege de verschillende kolomtoevoegingen in de loop van de tijd. Ik weet niet zeker of je dat nu kunt oplossen, maar idealiter zou je altijd ANSI_PADDING AAN hebben , of op zijn minst dezelfde instelling hebben voor alle ALTER TABLE verklaringen.
  3. Overweeg om 2 extra bestandsgroepen te maken:tabellen en indexen. Het is het beste om je spullen niet in PRIMARY te zetten want dat is waar SQL SERVER al zijn gegevens en metagegevens over uw objecten opslaat. U maakt uw tabel en geclusterde index (want dat zijn de gegevens voor de tabel) op [Tables] en alle niet-geclusterde indexen op [Indexen]
  4. Verhoog de vulfactor van 50%. Dit lage aantal is waarschijnlijk de reden waarom uw indexruimte groter is dan uw gegevensruimte. Door een Index Rebuild uit te voeren, worden de gegevenspagina's opnieuw gemaakt met een maximum van 4k (van de totale 8k paginagrootte) die voor uw gegevens wordt gebruikt, zodat uw tabel over een groot gebied wordt verspreid.
  5. Als de meeste of alle zoekopdrachten "ER101_ORG_CODE" hebben in de WHERE voorwaarde, overweeg dan om die naar de eerste kolom van de geclusterde index te verplaatsen. Ervan uitgaande dat het vaker wordt gebruikt dan "ER101_ORD_NBR". Als "ER101_ORD_NBR" vaker wordt gebruikt, bewaar het dan. Het lijkt erop dat, aangenomen dat de veldnamen "OrganizationCode" en "OrderNumber" betekenen, "OrgCode" een betere groepering is die meerdere "OrderNumbers" kan bevatten.
  6. Klein punt, maar als "ER101_ORG_CODE" altijd 2 tekens is, gebruik dan CHAR(2) in plaats van VARCHAR(2) omdat het een byte in de rijkop opslaat die variabele breedtematen bijhoudt en optelt over miljoenen rijen.
  7. Zoals anderen hier al hebben vermeld, gebruik je SELECT * prestatie zal schaden. Niet alleen omdat SQL Server alle kolommen moet retourneren en dus meer kans heeft om een ​​geclusterde indexscan uit te voeren, ongeacht uw andere indexen, maar het kost SQL Server ook tijd om naar de tabeldefinitie te gaan en * in alle kolomnamen. Het moet enigszins . zijn sneller om alle 238 kolomnamen op te geven in de SELECT lijst, hoewel dat het scanprobleem niet zal helpen. Maar heb je ooit echt alle 238 kolommen tegelijk nodig?

Veel succes!

UPDATE
Voor de volledigheid van de vraag "hoe de prestaties op een grote tafel voor ad-hocquery's te verbeteren", moet worden opgemerkt dat hoewel dit in dit specifieke geval niet helpt, ALS iemand SQL Server 2012 gebruikt (of nieuwer als die tijd komt) en ALS de tabel niet wordt bijgewerkt, is het gebruik van Columnstore-indexen een optie. Voor meer details over die nieuwe functie, kijk hier:http://msdn.microsoft.com/en-us/library/gg492088.aspx (ik geloof dat deze zijn gemaakt om te updaten vanaf SQL Server 2014).

UPDATE 2
Aanvullende overwegingen zijn:

  • Schakel compressie in op de geclusterde index. Deze optie is beschikbaar gekomen in SQL Server 2008, maar als een functie voor alleen Enterprise Edition. Vanaf SQL Server 2016 SP1 , Data Compression is beschikbaar gemaakt in alle edities! Zie de MSDN-pagina voor gegevenscompressie voor details over rij- en paginacompressie.
  • Als u gegevenscompressie niet kunt gebruiken, of als het niet veel voordeel oplevert voor een bepaalde tabel, ALS u een kolom van een type met vaste lengte heeft (INT , BIGINT , TINYINT , SMALLINT , CHAR , NCHAR , BINAIR , DATETIME , SMALLDATETIME , GELD , etc) en meer dan 50% van de rijen is NULL , overweeg dan om de SPARSE optie die beschikbaar kwam in SQL Server 2008. Zie de MSDN-pagina voor Sparse kolommen gebruiken voor details.


  1. FROM_UNIXTIME() Voorbeelden – MySQL

  2. Een Microsoft Access-database migreren naar SQL Server

  3. Hoe SQL Server op SUSE 12 te installeren

  4. Relationele versus niet-relationele databases - Deel 3