sql >> Database >  >> RDS >> Sqlserver

Drie eenvoudige overwinningen op SQL Server-prestaties

Zoals elke ervaren productie-DBA weet, staat u vaak onder grote druk om problemen met de databaseprestaties zo snel mogelijk te diagnosticeren en te verhelpen. Hier zijn drie dingen waar u, afhankelijk van uw werklast en infrastructuur, mogelijk voordeel uit kunt halen om een ​​zeer merkbare positieve invloed te hebben op uw databaseprestaties.

Basic Row Store Index Tuning

De meeste SQL Server-exemplaren die ik in mijn carrière ben tegengekomen, hadden relatief eenvoudige mogelijkheden voor het afstemmen van rij-opslagindexen. Een leuk aspect van het afstemmen van rij-opslagindexen is dat het vaker onder uw directe controle staat als een DBA, vooral in vergelijking met het afstemmen van query's of opgeslagen procedures, die vaak onder de controle staan ​​van ontwikkelaars of externe leveranciers.

Sommige DBA's zijn terughoudend met het afstemmen van indexen (vooral op databases van derden) omdat ze bang zijn iets te breken of de ondersteuning van leveranciers voor de database of toepassing in gevaar te brengen. Uiteraard moet u voorzichtiger zijn met databases van derden en proberen contact op te nemen met de leverancier voordat u zelf indexwijzigingen aanbrengt, maar in sommige situaties heeft u mogelijk geen ander haalbaar alternatief (behalve het gooien van snellere hardware en opslag op het probleem ).

U kunt een paar sleutelquery's uitvoeren vanuit mijn SQL Server Diagnostic Information Queries om een ​​goed idee te krijgen of u een aantal eenvoudige index-tuningmogelijkheden heeft voor uw instantie of database. U moet op uw hoede zijn voor ontbrekende indexverzoeken, ontbrekende indexwaarschuwingen, ondergebruikte of niet-gebruikte niet-geclusterde indexen en mogelijke mogelijkheden voor gegevenscompressie.

Er is wel enige ervaring, een goed beoordelingsvermogen en kennis van uw werklast nodig om de index goed af te stemmen. Het komt maar al te vaak voor dat mensen een onjuiste indexafstemming uitvoeren door overhaast veel indexwijzigingen aan te brengen zonder de juiste analyse te doen.

Hier zijn enkele vragen die ik graag gebruik, op databaseniveau:

-- Missing Indexes for current database by Index Advantage  (Query 1) (Missing Indexes)
 
SELECT DISTINCT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage], 
  migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
  mid.equality_columns, mid.inequality_columns, mid.included_columns,
  migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,
  OBJECT_NAME(mid.[object_id]) AS [Table Name], p.rows AS [Table Rows]
  FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
  INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
  ON migs.group_handle = mig.index_group_handle
  INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
  ON mig.index_handle = mid.index_handle
  INNER JOIN sys.partitions AS p WITH (NOLOCK)
  ON p.[object_id] = mid.[object_id]
  WHERE mid.database_id = DB_ID()
  AND p.index_id < 2 
  ORDER BY index_advantage DESC OPTION (RECOMPILE);
 
  ------
  -- Look at index advantage, last user seek time, number of user seeks to help determine source and importance
  -- SQL Server is overly eager to add included columns, so beware
  -- Do not just blindly add indexes that show up from this query!!!
 
  -- Find missing index warnings for cached plans in the current database  (Query 2) (Missing Index Warnings)
  -- Note: This query could take some time on a busy instance
 
  SELECT TOP(25) OBJECT_NAME(objectid) AS [ObjectName], 
                 cp.objtype, cp.usecounts, cp.size_in_bytes, query_plan
  FROM sys.dm_exec_cached_plans AS cp WITH (NOLOCK)
  CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
  WHERE CAST(query_plan AS NVARCHAR(MAX)) LIKE N'%MissingIndex%'
  AND dbid = DB_ID()
  ORDER BY cp.usecounts DESC OPTION (RECOMPILE);
 
  ------
  -- Helps you connect missing indexes to specific stored procedures or queries
  -- This can help you decide whether to add them or not
  -- Possible Bad NC Indexes (writes >= reads)  (Query 3) (Bad NC Indexes)
 
  SELECT OBJECT_NAME(s.[object_id]) AS [Table Name], i.name AS [Index Name], i.index_id, 
  i.is_disabled, i.is_hypothetical, i.has_filter, i.fill_factor,
  s.user_updates AS [Total Writes], s.user_seeks + s.user_scans + s.user_lookups AS [Total Reads],
  s.user_updates - (s.user_seeks + s.user_scans + s.user_lookups) AS [Difference]
  FROM sys.dm_db_index_usage_stats AS s WITH (NOLOCK)
  INNER JOIN sys.indexes AS i WITH (NOLOCK)
  ON s.[object_id] = i.[object_id]
  AND i.index_id = s.index_id
  WHERE OBJECTPROPERTY(s.[object_id],'IsUserTable') = 1
  AND s.database_id = DB_ID()
  AND s.user_updates > (s.user_seeks + s.user_scans + s.user_lookups)
  AND i.index_id > 1 AND i.[type_desc] = N'NONCLUSTERED'
  AND i.is_primary_key = 0 AND i.is_unique_constraint = 0 AND i.is_unique = 0
  ORDER BY [Difference] DESC, [Total Writes] DESC, [Total Reads] ASC OPTION (RECOMPILE);
 
  ------
  -- Look for indexes with high numbers of writes and zero or very low numbers of reads
  -- Consider your complete workload, and how long your instance has been running
  -- Investigate further before dropping an index!
  -- Breaks down buffers used by current database by object (table, index) in the buffer cache  (Query 4) (Buffer Usage)
  -- Note: This query could take some time on a busy instance
  SELECT OBJECT_NAME(p.[object_id]) AS [Object Name], p.index_id, 
  CAST(COUNT(*)/128.0 AS DECIMAL(10, 2)) AS [Buffer size(MB)],  
  COUNT(*) AS [BufferCount], p.[Rows] AS [Row Count],
  p.data_compression_desc AS [Compression Type]
  FROM sys.allocation_units AS a WITH (NOLOCK)
  INNER JOIN sys.dm_os_buffer_descriptors AS b WITH (NOLOCK)
  ON a.allocation_unit_id = b.allocation_unit_id
  INNER JOIN sys.partitions AS p WITH (NOLOCK)
  ON a.container_id = p.hobt_id
  WHERE b.database_id = CONVERT(int, DB_ID())
  AND p.[object_id] > 100
  AND OBJECT_NAME(p.[object_id]) NOT LIKE N'plan_%'
  AND OBJECT_NAME(p.[object_id]) NOT LIKE N'sys%'
  AND OBJECT_NAME(p.[object_id]) NOT LIKE N'xml_index_nodes%'
  GROUP BY p.[object_id], p.index_id, p.data_compression_desc, p.[Rows]
  ORDER BY [BufferCount] DESC OPTION (RECOMPILE);
 
  ------
  -- Tells you what tables and indexes are using the most memory in the buffer cache
  -- It can help identify possible candidates for data compression

Uitgestelde duurzaamheid gebruiken

De functie voor vertraagde duurzaamheid is in SQL Server 2014 aan het product toegevoegd en is dus al geruime tijd beschikbaar. Vertraagde duurzame transactie-commits zijn asynchroon en rapporteren een transactie-commit als succesvol voor de logrecords voor de transactie worden daadwerkelijk naar het opslagsubsysteem geschreven. Vertraagde duurzame transacties worden pas duurzaam als de transactielogboekvermeldingen naar de schijf zijn gewist.

Deze functie is beschikbaar in alle edities van SQL Server. Desondanks zie ik het zelden worden gebruikt als ik naar klantendatabases kijk. Vertraagde duurzaamheid opent de mogelijkheid van enig gegevensverlies, tot een volledige logbuffer in het slechtste geval (zoals uitgelegd door Paul Randal hier), dus het is zeker niet geschikt voor een RPO-scenario waarin absoluut geen gegevensverlies acceptabel is.

Vertraagde duurzaamheid vermindert transactielatentie omdat het niet wacht tot log IO is voltooid en de controle teruggeeft aan de client, en het vermindert ook vergrendeling en schijfconflicten voor gelijktijdige transacties. Deze twee voordelen kunnen vaak een zeer positief effect hebben op uw query- en applicatieprestaties met de juiste zeer schrijfzware werklast.

Vertraagde duurzaamheid helpt meestal zware OLTP-workloads met zeer frequente, kleine schrijftransacties waarbij u een hoge schrijflatentie op bestandsniveau ziet van sys.dm_io_virtual_file_stats op het transactielogbestand en/of u ziet hoge WRITELOG-wachttijden van sys. dm_os_wait_stats.

U kunt SQL Server 2014 of nieuwer eenvoudig dwingen om vertraagde duurzaamheid te gebruiken voor alle transacties (zonder codewijzigingen) door de volgende opdracht uit te voeren:

ALTER DATABASE AdventureWorks2014 SET DELAYED_DURABILITY = FORCED;

Ik heb klanten gehad die vertraagde duurzaamheid programmatisch in- en uitschakelden op verschillende tijdstippen van de dag (zoals tijdens geplande ETL- of onderhoudsactiviteiten). Ik heb ook klanten gehad die te allen tijde vertraagde duurzaamheid gebruiken, omdat ze een geschikte werkbelasting en risicotolerantie voor gegevensverlies hebben.

Ten slotte heb ik klanten gehad die nooit zouden overwegen om uitgestelde duurzaamheid te gebruiken, of het gewoon niet nodig hebben met hun werklast. Als u vermoedt dat uw werklast mogelijk profiteert u van het gebruik van vertraagde duurzaamheid, maar maakt u zich zorgen over het mogelijke gegevensverlies, dan zijn er andere alternatieven die u kunt overwegen.

Een alternatief is de permanente logboekbufferfunctie in SQL Server 2016 SP1, waar u een tweede transactielogboekbestand van 20 MB kunt maken op een DAX-opslagvolume (Direct Access Mode) dat wordt gehost op een NV-DIMM-persistent geheugenapparaat. Dit extra transactielogbestand wordt gebruikt om de staart van het logboek in de cache op te slaan, met toegang op byteniveau die de conventionele opslagstack op blokniveau omzeilt.

Als u denkt dat uw werklast baat kan hebben bij het gebruik van de permanente logbufferfunctie, kunt u experimenteren met het tijdelijk gebruiken van vertraagde duurzaamheid om te zien of er daadwerkelijk prestatievoordeel is met uw werklast voordat u het geld uitgeeft aan het permanente NV-DIMM-geheugen dat u zou de aanhoudende logbufferfunctie moeten gebruiken.

Temdb verplaatsen naar Intel Optane DC P4800X-opslag

Ik heb veel succes gehad met verschillende recente klanten die hun tempdb-databasebestanden van een ander type opslag naar een logische schijf hebben verplaatst die werd ondersteund door een paar Intel Optane DC P4800X PCIe NVMe-opslagkaarten (in een software RAID 1-array).

Deze geheugenkaarten zijn verkrijgbaar in capaciteiten van 375 GB, 750 GB en 1,5 TB (hoewel de capaciteit van 1,5 TB gloednieuw is en nog steeds moeilijk te vinden is). Ze hebben een extreem lage latentie (veel lager dan welk type NAND-flashopslag dan ook), uitstekende willekeurige I/O-prestaties bij lage wachtrijdiepten (veel beter dan NAND-flashopslag), met consistente leesresponstijden bij een zeer zware schrijfwerkbelasting.

Ze hebben ook een hoger schrijfuithoudingsvermogen dan "schrijfintensieve" enterprise NAND-flashopslag, en hun prestaties verslechteren niet omdat ze bijna vol zijn. Deze kenmerken maken deze kaarten uitermate geschikt voor veel zware tempdb-workloads, met name zware OLTP-workloads en situaties waarin u RCSI gebruikt in uw gebruikersdatabases (waardoor de resulterende versieopslagworkload op tempdb komt te staan).

Het is ook heel gebruikelijk om een ​​hoge schrijfvertraging op bestandsniveau te zien op tempdb-gegevensbestanden van de sys.dm_io_virtual_file_stats DMV, dus het verplaatsen van uw tempdb-gegevensbestanden naar Optane-opslag is een manier om dat probleem direct aan te pakken, dat kan sneller en gemakkelijker zijn dan conventioneel werklast afstemmen.

Een ander mogelijk gebruik voor Optane-opslagkaarten is als een huis voor uw transactielogbestand(en). U kunt Optane-opslag ook gebruiken met oudere versies van SQL Server (zolang uw besturingssysteem en hardware dit ondersteunen). Het is een mogelijk alternatief voor het gebruik van vertraagde duurzaamheid (waarvoor SQL Server 2014 vereist is) of het gebruik van de persistente logbufferfunctie (waarvoor SQL Server 2016 SP1) vereist is.

Conclusie

Ik heb drie technieken besproken voor het scoren van een snelle prestatiewinst met SQL Server:

  • Conventionele afstemming van de rij-opslagindex is van toepassing op alle versies van SQL Server, en het is een van de beste tools in je arsenaal.
  • Vertraagde duurzaamheid is beschikbaar in SQL Server 2014 en nieuwer, en het kan erg voordelig zijn bij sommige soorten werkbelasting (en RPO-vereisten). Persisted log-buffer is beschikbaar in SQL Server 2016 SP1 en biedt vergelijkbare voordelen als vertraagde duurzaamheid, zonder het gevaar van gegevensverlies.
  • Het verplaatsen van bepaalde typen databasebestanden naar Intel Optane-opslag kan prestatieproblemen met tempdb of met gebruikersdatabasetransactielogbestanden helpen verlichten. U kunt Optane-opslag gebruiken met oudere versies van SQL Server en er zijn geen code- of configuratiewijzigingen vereist.

  1. Een overzicht van Amazon RDS &Aurora-aanbiedingen voor PostgreSQL

  2. MariaDB VERSIE() Uitgelegd

  3. Proactieve SQL Server Health Checks, Deel 1:Schijfruimte

  4. Is het mogelijk om naar kolomnamen te verwijzen via bindvariabelen in Oracle?