Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查询每隔几天就会变慢_Sql_Sql Server_Database - Fatal编程技术网

SQL查询每隔几天就会变慢

SQL查询每隔几天就会变慢,sql,sql-server,database,Sql,Sql Server,Database,我有一个多年来一直运行良好的问题,但突然它开始减速很多。从几乎瞬间到25秒。 经过一些研究,结果证明问题出在索引上。重新组织和重建查询使用的四个表的所有索引修复了该问题 太好了,我想一切都好了。但几天后,又出现了同样的问题。重建索引修复了它,但它开始每隔几天恢复一次。查询速度减慢=>重建索引。 这些表格相当稳定,一周内添加了几百个项目,它们有大约30万条记录 这可能是什么原因 编辑: 关于这个问题,我不知道如何在不破坏东西的情况下提高效率 ALTER PROCEDURE [dbo].[odat_

我有一个多年来一直运行良好的问题,但突然它开始减速很多。从几乎瞬间到25秒。 经过一些研究,结果证明问题出在索引上。重新组织和重建查询使用的四个表的所有索引修复了该问题

太好了,我想一切都好了。但几天后,又出现了同样的问题。重建索引修复了它,但它开始每隔几天恢复一次。查询速度减慢=>重建索引。 这些表格相当稳定,一周内添加了几百个项目,它们有大约30万条记录

这可能是什么原因

编辑:

关于这个问题,我不知道如何在不破坏东西的情况下提高效率

ALTER PROCEDURE [dbo].[odat_PricesByDealer]
(
    @dealer_id          int,
    @dealergroup_id     int,
    @startdate          datetime,
    @pricetype_id       int,
    @product_groep      nvarchar(30)
)
AS
    SET NOCOUNT ON

    IF @pricetype_id = 0
        SET @pricetype_id = NULL

    IF @product_groep = '0'
        SET @product_groep = NULL

    SELECT a.price_ID 
        , a.make_id
        , e.make_code_name
        , a.dealergroup_ID
        , c.product_ID
        , c.product_code
        , c.product_department
        , c.product_code_name       
        , c.product_groep
        , c.product_subgroep1
        , c.product_subgroep2
        , c.product_producent
        , b.pricerow_lowerbound
        , b.pricerow_upperbound
        , b.pricerow_value
        , aa.startdate AS startdate
        , a.price_enddate AS enddate
        , d.pricetype_id
        , d.pricetype_name
        , 3 AS price_level
    FROM dbo.tblPrices a WITH (NOLOCK) 
    JOIN udf_PricesByDealer(@dealer_id, @startdate) aa ON a.price_startdate = aa.startdate
        AND a.product_id = aa.product_id
        AND a.pricetype_ID = aa.pricetype_ID
        AND a.make_ID = aa.make_ID
        AND a.dealergroup_ID = aa.dealergroup_ID
        AND a.dealer_ID = aa.dealer_ID
    JOIN dbo.tblPriceRows b WITH (NOLOCK) ON a.price_ID = b.price_ID
    JOIN dbo.tblProducts c WITH (NOLOCK) ON a.product_ID = c.product_ID
    JOIN dbo.tblPriceTypes d WITH (NOLOCK) ON a.pricetype_ID = d.pricetype_ID
    JOIN dbo.tblMakes e WITH (NOLOCK) ON a.make_ID = e.make_ID
    WHERE a.make_ID <> 0 
        AND a.dealergroup_ID = @dealergroup_id
        AND a.dealer_ID = @dealer_id
        AND (d.pricetype_id = @pricetype_id OR @pricetype_id IS NULL)
        AND (c.product_groep = @product_groep OR @product_groep IS NULL)
        AND a.price_authorized = 1
        AND c.product_exclude_from_pricelist = 0

若索引中的碎片较少,那个么可以重新组织索引,若不能重新生成索引的话。如果重建索引解决了问题,那么在实例上创建相应的索引维护计划,以进行适当的索引维护。同时更新统计信息,但如果在相关数据库上启用了自动更新统计信息,则会自动更新统计信息


主要方面是调整查询。

Punter015已经发布,您必须调整数据库,例如使用维护计划。 因为你不知道是否有必要,我在做了一些调查后,在网上找到了一些样品,最后做了这个程序,就遇到了同样的问题

它检查是否需要重新索引,然后执行重新索引。我每天晚上都用cron任务sqlcmd.exe运行它。不知道这是否是最好的方法,但对我来说效果很好

CREATE PROCEDURE [dbo].[proc_ReorganizeIndexes]
AS
BEGIN

  DECLARE @table nvarchar(100);
  DECLARE @index_name nvarchar(100);
  DECLARE @ext_frag float;
  DECLARE @int_frag float;
  DECLARE @sql nvarchar(max);
  DECLARE local_index_cursor CURSOR FOR

  SELECT object_name(dt.object_id) Tablename
      ,si.name IndexName
      ,dt.avg_fragmentation_in_percent AS ExternalFragmentation
      ,dt.avg_page_space_used_in_percent AS InternalFragmentation
  FROM
  (
      SELECT object_id,index_id,avg_fragmentation_in_percent,avg_page_space_used_in_percent
      FROM sys.dm_db_index_physical_stats (db_id(DB_NAME()),null,null,null,'DETAILED'
  )
  WHERE index_id <> 0) AS dt 
  INNER JOIN sys.indexes si ON si.object_id=dt.object_id 
         AND si.index_id=dt.index_id AND dt.avg_fragmentation_in_percent>10
         AND dt.avg_page_space_used_in_percent<75 ORDER BY avg_fragmentation_in_percent DESC 

  OPEN local_index_cursor
  FETCH NEXT FROM local_index_cursor
  INTO @table, @index_name, @ext_frag, @int_frag

    WHILE @@FETCH_STATUS = 0
    BEGIN

      PRINT 'Need rebuild: ' + @table+ ' for index ' + @index_name + ' Fragmentation (int/ext): ' + CAST(@int_frag AS varchar(100)) + ' / ' + CAST(@ext_frag AS varchar(100))
    SET @sql = 'ALTER INDEX ALL ON ' + @table + ' REBUILD WITH (FILLFACTOR=90)'
      EXEC sp_executesql @sql

      FETCH NEXT FROM local_index_cursor
      INTO @table, @index_name, @ext_frag, @int_frag
    END

  CLOSE local_index_cursor
  DEALLOCATE local_index_cursor

END

重建索引是第一步。您还可以检查执行计划,查看瓶颈在哪里,并重构查询以提高性能。如果您将罪魁祸首查询和执行计划作为屏幕截图发布,您可能会得到更多帮助。您是否尝试过更新统计信息而不是重建索引?不确定这是否会有帮助,但只是把它放在那里。你能详细说明什么是“坏”索引吗?
ALTER FUNCTION [dbo].[udf_GetMakeIdForDealer]
(
    @dealer_ID numeric
)
RETURNS TABLE
AS
RETURN
(
    SELECT m.make_ID
        , m.make_code_name
    FROM [dbo].[tblMakes] m WITH (NOLOCK)
    WHERE (m.make_ID in  (SELECT make_ID 
                        FROM tblDealerGroupMakes WITH (NOLOCK)
                        WHERE dealergroup_ID = (SELECT dealergroup_ID 
                                                FROM tblDealers WITH (NOLOCK)
                                                WHERE dealer_ID = @dealer_ID))
            OR 
            m.make_ID IN (SELECT make_ID 
                        FROM tblDealerMakes WITH (NOLOCK)
                        WHERE dealer_ID = @dealer_ID AND dealermake_exclude = 0))
        AND m.make_ID NOT IN (SELECT make_ID 
                            FROM tblDealerMakes WITH (NOLOCK)
                            WHERE dealer_ID = @dealer_ID AND dealermake_exclude = 1)
)
CREATE PROCEDURE [dbo].[proc_ReorganizeIndexes]
AS
BEGIN

  DECLARE @table nvarchar(100);
  DECLARE @index_name nvarchar(100);
  DECLARE @ext_frag float;
  DECLARE @int_frag float;
  DECLARE @sql nvarchar(max);
  DECLARE local_index_cursor CURSOR FOR

  SELECT object_name(dt.object_id) Tablename
      ,si.name IndexName
      ,dt.avg_fragmentation_in_percent AS ExternalFragmentation
      ,dt.avg_page_space_used_in_percent AS InternalFragmentation
  FROM
  (
      SELECT object_id,index_id,avg_fragmentation_in_percent,avg_page_space_used_in_percent
      FROM sys.dm_db_index_physical_stats (db_id(DB_NAME()),null,null,null,'DETAILED'
  )
  WHERE index_id <> 0) AS dt 
  INNER JOIN sys.indexes si ON si.object_id=dt.object_id 
         AND si.index_id=dt.index_id AND dt.avg_fragmentation_in_percent>10
         AND dt.avg_page_space_used_in_percent<75 ORDER BY avg_fragmentation_in_percent DESC 

  OPEN local_index_cursor
  FETCH NEXT FROM local_index_cursor
  INTO @table, @index_name, @ext_frag, @int_frag

    WHILE @@FETCH_STATUS = 0
    BEGIN

      PRINT 'Need rebuild: ' + @table+ ' for index ' + @index_name + ' Fragmentation (int/ext): ' + CAST(@int_frag AS varchar(100)) + ' / ' + CAST(@ext_frag AS varchar(100))
    SET @sql = 'ALTER INDEX ALL ON ' + @table + ' REBUILD WITH (FILLFACTOR=90)'
      EXEC sp_executesql @sql

      FETCH NEXT FROM local_index_cursor
      INTO @table, @index_name, @ext_frag, @int_frag
    END

  CLOSE local_index_cursor
  DEALLOCATE local_index_cursor

END