6

昨日、通常1秒以内に完了するストアドプロシージャを作成しました。今日は約18秒かかります。昨日も問題が発生しましたが、ストアドプロシージャを削除して再作成することで解決したようです。今日、そのトリックは機能していないようです。:(

興味深いことに、ストアドプロシージャの本体をコピーして、簡単なクエリとして実行すると、すぐに完了します。速度を低下させているのはストアドプロシージャであるという事実のようです...!

誰かが問題が何であるか知っていますか?回答を検索しましたが、Query Analyserを使用して実行することを推奨することがよくありますが、それはありません。現在、SQL Server2008Expressを使用しています。

ストアドプロシージャは次のとおりです。

ALTERPROCEDURE[dbo]。[spGetPOIs]
    @ lat1フロート、
    @ lon1フロート、
    @ lat2フロート、
    @ lon2フロート、
    @minLOD tinyint、
    @maxLOD tinyint、
    @exactビット
なので
始める
    -クエリ長方形をポリゴンとして作成します
    @boundsgeographyを宣言します。
    SET @bounds = dbo.fnGetRectangleGeographyFromLatLons(@ lat1、@ lon1、@ lat2、@ lon2);

    -選択を実行します
    if(@exact = 0)
    始める
        SELECT [ID]、[Name]、[Type]、[Data]、[MinLOD]、[MaxLOD]、[Location]。[Lat] AS [Latitude]、[Location]。[Long] AS [Longitude]、[ SourceID]
        [POI]から
        どこ
            NOT((@maxLOD [MaxLOD]))AND
            (@ bounds.Filter([Location])= 1)
    終わり
    そうしないと
    始める
        SELECT [ID]、[Name]、[Type]、[Data]、[MinLOD]、[MaxLOD]、[Location]。[Lat] AS [Latitude]、[Location]。[Long] AS [Longitude]、[ SourceID]
        [POI]から
        どこ
            NOT((@maxLOD [MaxLOD]))AND
            (@ bounds.STIntersects([Location])= 1)
    終わり

終わり

'POI'テーブルには、MinLOD、MaxLODのインデックス、およびLocationの空間インデックスがあります。

4

3 に答える 3

4

ああ、それはクエリプランがダメなのだろうか?

SPのコンパイル/クエリlpanは、パラメータに応じて、最初の使用で決定されます。したがって、最初の呼び出しのパラメーター(lpanが存在しない場合)がクエリプランを決定します。ある時点で、私はキャッシュから削除され、新しいプランが生成されます。

次回の実行が遅い場合は、クエリアナライザを使用して呼び出しを行い、選択したプランを取得して、どのように表示されるかを確認します。

これである場合-オプトンを挿入して、すべての呼び出しでSPを再コンパイルします(再コンパイルを使用)。

于 2010-03-17T13:03:02.470 に答える
2

パラメータスニッフィンググーグルそれ。これを試してください。これにより、入力パラメーターがローカル変数に「再マップ」され、SQLServerがパラメーターに基づいてクエリプランを推測しようとするのを防ぎます。

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
于 2010-03-17T13:03:07.807 に答える
0

同様の問題があり、インデックスに関連していました。
それらを再構築すると、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
于 2017-04-12T11:34:40.940 に答える