Teilen Sie SQL Server mit, dass eine Abfrage ad hoc erfolgt und nicht darauf basierend optimiert werden soll

7

Gibt es eine Möglichkeit, eine einmalige Abfrage für eine SQL Server-Produktionsdatenbank auszuführen und sie anzuweisen, auf der Grundlage dieser Abfrage keine zukünftigen Beurteilungen vorzunehmen? ZB Ausführungspläne speichern, Indizes empfehlen usw.

Oder vielleicht sollte ich nicht so besorgt sein.

Kevin Kalitowski
quelle

Antworten:

2

Gibt es eine Möglichkeit, eine einmalige Abfrage für eine SQL Server-Produktionsdatenbank auszuführen und sie anzuweisen, auf der Grundlage dieser Abfrage keine zukünftigen Beurteilungen vorzunehmen? ZB Ausführungspläne speichern, Indizes empfehlen usw.

Bevor ich Ihre Frage beantworte, müssen Sie den Hintergrund verstehen.

Cache planen:


Bevor ein Abfragestapel auf SQL Server ausgeführt wird, wird der Stapel in einen Plan kompiliert. Der Plan wird dann ausgeführt, um seine Auswirkungen zu erzielen oder Ergebnisse zu erzielen.

Das Kompilieren von Ausführungsplänen ist eine relativ teure Operation, daher wird versucht, diese Kosten zu vermeiden, indem die kompilierten Pläne in einem SQL Server-Speicherbereich zwischengespeichert werden, der als Plan-Cache bezeichnet wird. Wenn ein weiterer Abfragebatch ausgeführt werden muss, durchsucht SQL Server den Plan-Cache nach möglichen Möglichkeiten zur Wiederverwendung von Plänen. Wenn die Wiederverwendung des Plans erreicht wird, werden die Kompilierungskosten vermieden.

SQL Server entscheidet über die geeignete Zuweisung von Speicher zum Plan-Cache aus dem Pufferpool.

Geben Sie hier die Bildbeschreibung ein

Da Ihre Frage auf Ad-hoc-Abfragen ausgerichtet ist , können Sie sich ein Bild davon machen, wie sich Ad-hoc-Abfragen auf den Plan-Cache auswirken.

Eine Ad-hoc-Abfrage ist ein TSQL-Stapel, der keine Parameter enthält und nicht vorbereitet ist.

SQL Server erfordert eine genaue Textübereinstimmung für zwei Ad-hoc-Abfragen, bevor eine Wiederverwendung erfolgen kann. Bei der Textübereinstimmung wird sowohl zwischen Groß- und Kleinschreibung unterschieden, auch auf Servern ohne Berücksichtigung der Groß- und Kleinschreibung.

-- get a count of the number of adhoc query plans use
select count(*) as CountOfAdHocQP from sys.dm_Exec_Cached_plans
where cacheobjtype = 'Compiled Plan'
and objtype = 'Adhoc'

Die obigen Antworten schlagen vor, einen Abfragehinweis OPTION (RECOMPILE)oder einen -xSchalter zu verwenden.

Da Sie eine bestimmte ad-hocAbfrage kennen, die Sie ausführen, und den Plan nicht zwischenspeichern möchten (wir werden später auf fehlende Index-DMV-Details stoßen), können Sie diese verwendenDBCC FREEPROCCACHE (@plan_handle);

-- for details, refer above ooutwire's code : http://dba.stackexchange.com/a/112571/8783
declare  @plan_handle as varbinary(64)

SELECT  @plan_handle = cp.plan_handle 
FROM sys.dm_exec_cached_plans AS cp 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE [text] LIKE  N'%FROM
    dbo.tbl
WHERE
    c2%' -- here goes your EXACT query (along with WHITE SPACE, case UPPER or lower, etc) text to search !!
option (recompile)
select @plan_handle as PlanHandle
DBCC FREEPROCCACHE (@plan_handle); -- remove the plan handle !! ***CAUTION***

Geben Sie hier die Bildbeschreibung ein

Dies verhindert nicht, dass die Ad-hoc-Abfrage in der Liste der vorgeschlagenen Indizes angezeigt wird. Ich habe eine Abfrage ausgeführt, die von einem Index profitieren würde, und sie wurde in sys.dm_db_missing_index_details angezeigt. Wählen Sie x aus y, wobei z> '8/1/15' Option ist (neu kompilieren)

Es gibt keine Möglichkeit , löschen / Reset - Statistiken für dm_db_missing_index_columns, dm_db_missing_index_groups, dm_db_missing_index_group_statsund dm_db_missing_index_detailswie DBCC SQLPERF (‘sys.dm_os_wait_stats’, CLEAR). Weitere Informationen finden Sie unter Löschen von Vorschlägen zum Fehlen eines Index für eine einzelne Tabelle

Oder vielleicht sollte ich nicht so besorgt sein.

Sie sollten sich keine Sorgen machen, wenn die Abfrage nur "EIN AUS" lautet. Wenn Sie der Meinung sind, dass Sie weitere "AD HOC" -Abfragen ausführen müssen, aktivieren Sie die Option.optimize for ad hoc workloads sp_configure

Referenz: Planen Sie das Zwischenspeichern und Neukompilieren in SQL Server 2012

Kin Shah
quelle
7

Sie können den Abfragehinweis hinzufügen OPTION (RECOMPILE).

Dadurch wird SQL Server effektiv mitgeteilt: "Geben Sie mir einen Plan, um diese Abfrage einmal auszuführen, aber speichern Sie ihn nicht im Plan-Cache."

Werfen Sie einen Blick auf Kendra Littles Artikel über RECOMPILEHinweise und das Zwischenspeichern von Ausführungsplänen. Sie deckt alle Verwendungszwecke und möglichen Auswirkungen ab.

RECOMPILE Hinweise und Caching des Ausführungsplans

Siehe auch:

Parameter Sniffing, Embedding und die RECOMPILE-Optionen

In Bezug auf das Deaktivieren der fehlenden Indexfunktion besteht die einzige unterstützte Möglichkeit darin, SQL Server über die Befehlszeile mit dem -xSwitch zu starten . Das ist nicht das, was Sie wollen, aber es begrenzt Ihre Optionen.

Kris Gruttemeyer
quelle
4

Housekeeping :

Ich verwende SQL Server Microsoft SQL Server 2012 - 11.0.5343.0 (X64)

Lösung :

Sie können WITH RECOMPILE in Ihrer gespeicherten Prozedur verwenden.

Erstellen Sie zunächst eine Testdatenbank, eine Tabelle, einige Indizes und schließlich Testdaten.

USE [master];
GO

IF DATABASEPROPERTYEX (N'test', N'Version') > 0
BEGIN
    ALTER DATABASE [test] SET SINGLE_USER
        WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [test];
END
GO

CREATE DATABASE [test];
GO

USE [test];
GO

IF OBJECT_ID('dbo.tbl','U') IS NOT NULL
BEGIN
    DROP TABLE dbo.tbl;
END;
CREATE TABLE dbo.tbl
(
      c1 INT NOT NULL
    , c2 DATETIME NOT NULL
    , c3 CHAR(7000) NOT NULL  
);
GO

-- Insert 20,000 different dates
INSERT INTO dbo.tbl 
    SELECT DISTINCT TOP 1000
        number
      , DATEADD(DAY , number , GETDATE())
      , 'a'  
    FROM
        master..spt_values
    WHERE
        number > 0;
GO 20


-- Add a couple indexes
-- This is a non-unique clustered index
--   so, there will be a 4-byte uniqueifier column
--   added to the row within the page
CREATE CLUSTERED INDEX CIX_tbl_c1
    ON dbo.tbl (c1 ASC);
GO
--CREATE NONCLUSTERED INDEX IX_tbl_c2
--    ON dbo.tbl (c2 ASC);
--GO

Fügen Sie eine gespeicherte Prozedur hinzu:

USE [test];
GO

CREATE PROCEDURE dbo.TestProc @i INT
       --WITH RECOMPILE
AS 
       SELECT DISTINCT
           c1
       FROM
           dbo.tbl
       WHERE
           c1 = @i;
GO

Geben Sie jetzt Ihren Cache frei (tun Sie dies nicht in der Produktion!) Und überprüfen Sie ihn.

-- Free your cache
DBCC FREEPROCCACHE;
GO

-- What is in my cache?
USE [master];
GO

SELECT
    usecounts
  , refcounts
  , cacheobjtype
  , objtype
  , DB_NAME([dbid])
  , [sql]
FROM
    syscacheobjects
ORDER BY
    [dbid]
  , usecounts DESC
  , objtype;
GO

Führen Sie Ihre Prozedur einmal aus und überprüfen Sie den Cache.

-- Execute my stored procedure once
USE [test];
GO
EXEC dbo.TestProc @i = 10;
GO

-- Re-check the cache
USE [master];
GO

SELECT
    usecounts
  , refcounts
  , cacheobjtype
  , objtype
  , DB_NAME([dbid])
  , [sql]
FROM
    syscacheobjects
ORDER BY
    [dbid]
  , usecounts DESC
  , objtype;
GO

Ihr Plan ist da und wurde einmal verwendet:

Geben Sie hier die Bildbeschreibung ein

Ändern Sie nun Ihre Prozedur MIT RECOMPILE.

-- Now, alter your procedure
USE [test];
GO

ALTER PROCEDURE dbo.TestProc @i INT
       WITH RECOMPILE
AS 
       SELECT DISTINCT
           c1
       FROM
           dbo.tbl
       WHERE
           c1 = @i;
GO

Geben Sie Ihren Cache noch einmal frei, führen Sie Ihre Prozedur aus und überprüfen Sie den Cache auf einen Eintrag.

-- Free your cache
DBCC FREEPROCCACHE;
GO

-- Execute my stored procedure once
USE [test];
GO
EXEC dbo.TestProc @i = 10;
GO

-- Re-check the cache
USE [master];
GO

SELECT
    usecounts
  , refcounts
  , cacheobjtype
  , objtype
  , DB_NAME([dbid])
  , [sql]
FROM
    syscacheobjects
ORDER BY
    [dbid]
  , usecounts DESC
  , objtype;
GO
</pre>

Es ist nicht da! Dies sollte Ihnen helfen. Geben Sie hier die Bildbeschreibung ein

Was nun die Indizes betrifft, können wir dieses Experiment ausprobieren:

USE [test];
GO

SELECT
    c2
FROM
    dbo.tbl
WHERE
    c2 > '09-15-2015';
GO

Hier ist der Ausführungsplan für diese Abfrage:

Ausführungsplan

Ich kann jetzt die Indexanforderung sehen.

SELECT
    index_handle
  , database_id
  , object_id
  , equality_columns
  , inequality_columns
  , included_columns
  , statement
FROM
    sys.dm_db_missing_index_details;
GO

Fehlender Index

ooutwire
quelle
@ooutwire Leider wollte ich vermeiden, dass meine fehlenden Indexansichten mit Ad-hoc-Abfragen überfüllt werden, da viele Ad-hoc-Abfragen nicht optimiert sind und in dieser Ansicht angezeigt werden. Aufgrund der anderen Beiträge scheint dies nicht möglich zu sein.
Kevin Kalitowski