質問

私は、一般的に第二の下で完了し、昨日、ストアドプロシージャを書かれています。今日では、約18秒かかります。私も昨日の問題に遭遇した、そしてストアドプロシージャをDROPing、再CREATEingによって解決されるように見えました。今日では、そのトリックは動作しているように表示されません。 :(

興味深いことに、私は、ストアドプロシージャの本体をコピーして、それがすぐに完了する簡単なクエリとしてそれを実行した場合。 ...それはそれを減速のストアドプロシージャだという事実のようです!

誰もが、問題が何であるか知っていますか?それを持って、私は答えを検索したが、多くの場合、彼らはクエリアナライザを通してそれを実行することをお勧めしますが、私が持っていない - 。今の私は、SQL Server 2008のExpressを使用しています。

次のように

ストアドプロシージャである。

ALTER PROCEDURE [dbo].[spGetPOIs]
    @lat1 float,
    @lon1 float,
    @lat2 float,
    @lon2 float,
    @minLOD tinyint, 
    @maxLOD tinyint,
    @exact bit
AS
BEGIN
    -- Create the query rectangle as a polygon
    DECLARE @bounds geography;
    SET @bounds = dbo.fnGetRectangleGeographyFromLatLons(@lat1, @lon1, @lat2, @lon2);

    -- Perform the selection
    if (@exact = 0)
    BEGIN
        SELECT [ID], [Name], [Type], [Data], [MinLOD], [MaxLOD], [Location].[Lat] AS [Latitude], [Location].[Long] AS [Longitude], [SourceID]
        FROM [POIs]
        WHERE
            NOT ((@maxLOD  [MaxLOD])) AND
            (@bounds.Filter([Location]) = 1)
    END
    ELSE
    BEGIN
        SELECT [ID], [Name], [Type], [Data], [MinLOD], [MaxLOD], [Location].[Lat] AS [Latitude], [Location].[Long] AS [Longitude], [SourceID]
        FROM [POIs]
        WHERE
            NOT ((@maxLOD  [MaxLOD])) AND
            (@bounds.STIntersects([Location]) = 1)
    END

END

'POI' 表はMinLOD、MaxLODのインデックス、および位置に空間インデックスを有している。

役に立ちましたか?

解決

ああ、それはクエリプランを吸うことができますか?

SPのコンパイルを取得/クエリLPANは最初の使用時にdeterined - パラメータに依存します。だから、最初の呼び出し(無LPANが存在しない)のパラメータは、クエリプランを決定します。 1 piontで私は新しい計画が生成され、キャッシュから削除されます。

次の時間は、それはおそらく、クエリアナライザを使用して電話をかけると、選択されたプランを取得し、ゆっくりと走る - 。そしてそれがどのように見えるか確認してください。

それは、このある場合 - 。(再コンパイルして)すべての呼び出しにSPを再コンパイルするOPTONに入れます。

他のヒント

パラメータスニッフィング<のhref = "http://www.google.com/search?hl=en&as_q=sql+server+parameter+sniffing&as_epq=&as_oq=&as_eq=&num=100&lr=&as_filetype=&ft=i&as_sitesearch=&as_qdr=すべての&as_rights =&as_occt =あらゆる&CR =&as_nlo =&as_nhi =&安全=画像」のrel = "nofollowをnoreferrer">それををグーグル。パラメータに基づいて、クエリプランを推測しようとしているからSQL Serverを防止するために、ローカル変数への入力パラメータを「再マップ」なる、これを試してみます:

ALTER PROCEDURE [dbo].[spGetPOIs]
    @lat1 float,
    @lon1 float,
    @lat2 float,
    @lon2 float,
    @minLOD tinyint, 
    @maxLOD tinyint,
    @exact bit
AS
BEGIN
DECLARE @X_lat1 float,
    @X_lon1 float,
    @X_lat2 float,
    @X_lon2 float,
    @X_minLOD tinyint, 
    @X_maxLOD tinyint,
    @X_exact bit



    -- Create the query rectangle as a polygon
    DECLARE @bounds geography;
    SET @bounds = dbo.fnGetRectangleGeographyFromLatLons(@X_lat1, @X_lon1, @lX_at2, @X_lon2);

    -- Perform the selection
    if (@exact = 0)
    BEGIN
        SELECT [ID], [Name], [Type], [Data], [MinLOD], [MaxLOD], [Location].[Lat] AS [Latitude], [Location].[Long] AS [Longitude], [SourceID]
        FROM [POIs]
        WHERE
            NOT ((@X_maxLOD  [MaxLOD])) AND
            (@bounds.Filter([Location]) = 1)
    END
    ELSE
    BEGIN
        SELECT [ID], [Name], [Type], [Data], [MinLOD], [MaxLOD], [Location].[Lat] AS [Latitude], [Location].[Long] AS [Longitude], [SourceID]
        FROM [POIs]
        WHERE
            NOT ((@X_maxLOD  [MaxLOD])) AND
            (@bounds.STIntersects([Location]) = 1)
    END

END

私は同様の問題を持っていたし、それはインデックスと関連していた。
彼らは速い再実行するためにSPを助ける再構築ます。

私はここに解決策を見つけました

USE master;
GO

CREATE PROC DatabaseReIndex(@Database VARCHAR(100)) AS 
BEGIN
  DECLARE @DbID SMALLINT=DB_ID(@Database)--Get Database ID
  IF EXISTS(SELECT * FROM tempdb.sys.objects WHERE name='Indexes') 
  BEGIN --Delete Temp Table if exists, then create
    DROP TABLE TempDb.dbo.Indexes
  END

CREATE TABLE TempDb.dbo.Indexes(IndexTempID INT IDENTITY(1,1),SchemaName NVARCHAR(128),TableName NVARCHAR(128),IndexName NVARCHAR(128),IndexFrag FLOAT)
EXEC ('USE '+@Database+';
INSERT INTO TempDb.dbo.Indexes(TableName,SchemaName,IndexName,IndexFrag)
SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName,sch.name,ind.name IndexName,indexstats.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats('+@DbID+', NULL, NULL, NULL, NULL) indexstats
INNER JOIN sys.indexes ind ON ind.object_id = indexstats.object_id AND ind.index_id = indexstats.index_id
INNER JOIN sys.objects obj on obj.object_id=indexstats.object_id
INNER JOIN sys.schemas as sch ON sch.schema_id = obj.schema_id
WHERE indexstats.avg_fragmentation_in_percent > 10 AND indexstats.index_type_desc<>''HEAP''
ORDER BY indexstats.avg_fragmentation_in_percent DESC')--Get index data and fragmentation, set the percentage as high or low as you need

DECLARE @IndexTempID BIGINT=0,@SchemaName NVARCHAR(128),@TableName NVARCHAR(128),@IndexName NVARCHAR(128),@IndexFrag FLOAT
SELECT * FROM TempDb.dbo.Indexes --View your results, comment out if not needed...

-- Loop through the indexes
WHILE @IndexTempID IS NOT NULL 
  BEGIN
    SELECT @SchemaName=SchemaName,@TableName=TableName,@IndexName=IndexName,@IndexFrag=IndexFrag FROM TempDb.dbo.Indexes WHERE IndexTempID=@IndexTempID
    IF @IndexName IS NOT NULL AND @SchemaName IS NOT NULL AND @TableName IS NOT NULL 
    BEGIN
      IF @IndexFrag<30. 
      BEGIN --Low fragmentation can use re-organise, set at 30 as per most articles
        PRINT 'USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REORGANIZE'
        EXEC('USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REORGANIZE')
      END
    ELSE 
      BEGIN --High fragmentation needs re-build
        PRINT 'USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REBUILD'
        EXEC('USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REBUILD')
      END
    END

    SET @IndexTempID=(SELECT MIN(IndexTempID) FROM TempDb.dbo.Indexes WHERE IndexTempID>@IndexTempID)
  END
END

DROP TABLE TempDb.dbo.Indexes

GO
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top