Sql Server通过tsql更改所有索引的填充因子值

时间:2013-05-14 11:39:03

标签: sql tsql azure bacpac fillfactor

我必须将我的数据库暴露到bacpac文件中以将其导入Azure。 当我尝试导出时,我得到一个错误,因为任何索引都有一个fillFactor值。

我已经找到了如何为所有索引设置fillFactor值但是我不能指定0,值必须在1到100之间。如果我在管理工作室中更改了值,我可以将其设置为0。

问题是我有很多索引需要更改,我想通过tsql将fillFactor值更改为所有索引。

任何想法?。

感谢。

6 个答案:

答案 0 :(得分:1)

SQL Azure显然不支持FILLFACTOR

"SQL Azure Database does not support specifying FILLFACTOR with the CREATE INDEX statement. If we create indexes in a SQL Azure database, we will find that the index fillfactor values are all 0."

您必须从FILLFACTOR脚本中删除所有CREATE INDEX语句。同样,也不支持SORT_IN_TEMPDBDATA_COMPRESSION以及其他几个选项。

可以找到SQL Azure中支持的关键字的完整列表here

更新:SQL Azure V12(2015年推出) 支持FILLFACTOR。请参阅here

答案 1 :(得分:1)

这不是一种直接的T-SQL方式。虽然它确实生成了一个可以应用于数据库的纯T-SQL解决方案。

您的结果可能会因您的数据库而异...例如,糟糕的参照完整性可能会使这一点变得更加棘手......

此外,您还有自己的风险免责声明: - )

  1. 获取要迁移到SSDT项目的数据库
  2. http://msdn.microsoft.com/en-us/library/azure/jj156163.aspx http://blogs.msdn.com/b/ssdt/archive/2012/04/19/migrating-a-database-to-sql-azure-using-ssdt.aspx

    这是一种很好的方式将任何架构迁移到Azure,无论如何......它只是创建一个bacpac文件...修复...导出...修复......等等...所以我建议您在将数据库迁移到Azure时随时执行此操作

    对于FILLFACTOR修复,我只是使用了一个find和replace来从生成的模式文件中删除所有FILLFACTORS ...幸运的是我使用的数据库都将它们都设置为90,因此很容易找到解决方案和替换(CTRL-SHIFT-F)...如果你的变化,那么你可以使用Visual Studio的RegEx查找功能来查找所有填充因子,并将它们从索引中删除。

    我在RegEx并不是那么棒,但我觉得这很有效

    WITH \((.)*FILLFACTOR(.)*\)
    

    此时,您必须修复围绕Azure合规性的任何其他例外情况。所提供的链接描述了如何执行此操作

    1. 现在,您已经拥有了符合AZURE SQL标准的SSDT项目。
    2. 这是你自己风险的部分

      我使用这些脚本从数据库中删除所有FK,PK和唯一约束。

      while(exists(select 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE IN  ('FOREIGN KEY', 'PRIMARY KEY', 'UNIQUE')))
      begin
          declare @sql nvarchar(2000)
          SELECT TOP 1 @sql=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME
          + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
          FROM information_schema.table_constraints
          WHERE CONSTRAINT_TYPE IN  ('FOREIGN KEY', 'PRIMARY KEY', 'UNIQUE')
          exec (@sql)
      end
      
      
      declare @qry nvarchar(max);
      select @qry = 
      (SELECT  'DROP INDEX [' + ix.name + '] ON [' + OBJECT_NAME(ID) + ']; '
      FROM  sysindexes ix
      WHERE   ix.Name IS NOT null and ix.OrigFillFactor <> 0
      for xml path(''));
      exec sp_executesql @qry
      

      我这样做是因为AFAIK完全删除填充因子选项的唯一方法是删除并重新创建索引。这带来了一系列层叠的问题: - 带有填充因子的PK需要FK掉线等......这可能是一种更聪明的方法,所以你不要这样做。删除所有FK和PK&#39;然后查看依赖树...

      1. 现在回到您的Azure Compliant SSDT项目,并针对您的数据库执行该项目的SCHEMA COMPARISON ...这将创建一个脚本,重新创建您的所有FK,PK&#39; s,和唯一约束(没有填充因子)....此时你可以点击&#34;更新&#34;或者您可以单击更新右侧的按钮,这将生成您可以使用的脚本...所以现在配备

        • 上面的脚本删除FK,Pks和Unique。
        • 由SSDT创建的脚本
        • 对所述脚本进行充分的测试和审查,以确保没有遗漏任何内容
      2. 您应该能够将当前数据库更新为符合Azure的SCHEMA

        其他想法:

        在我的情况下,生产数据库中的填充因子并没有真正做任何有用的事情。它们只是作为默认设置创建的。在您的情况下,填充因子可能很重要,因此请不要在非Azure制作框中将其全部删除,而不知道其后果。

        在对生产系统执行此操作时还需要考虑其他事项...例如,这可能会导致一些镜像延迟,并且可能会导致日志文件以您预期的方式增长。如果您直接申请生产,这两者都真的很重要......

        如果将它们全部设置为FILL FACTOR 100,它会很好: - /

        那里有第三方工具(我已经听说过)你可以用来迁移到Azure ......

        另一种选择是使用 https://sqlazuremw.codeplex.com/

        使用它来创建符合Azure的SCHEMA,然后使用BCP复制所有数据。

        但是如果你想让你当前的SCHEMA Azure兼容,那么你可以创建一个bacpac文件上传到Azure,这对我来说只有一次我必须这样做。

        修改 Azure V12支持填充因子

答案 2 :(得分:1)

对于单个数据库中的所有表来说更简单:

   select 'ALTER INDEX ALL ON ['
   + s.name+ '].['+ o.name+'] REBUILD WITH (FILLFACTOR = 99)' 
   from sys.objects o
   inner join sys.schemas s on o.schema_id = s.schema_id
   where type='u' and is_ms_shipped=0

生成您可以复制的语句&amp;执行。

答案 3 :(得分:0)

我找到了一个非常有用的脚本here,它可以为所有索引分配新值并重建它们。只要您不担心使用动态T-SQL,您可能会发现它对您的任务和环境很有用,只需适当地设置值即可。 (我没有在原始页面上找到许可证信息,所以我在这里复制了脚本)

DECLARE @Database VARCHAR(255)  
DECLARE @Table VARCHAR(255)  
DECLARE @cmd NVARCHAR(500)  
DECLARE @fillfactor INT

SET @fillfactor = 90

DECLARE DatabaseCursor CURSOR FOR  
SELECT name FROM master.dbo.sysdatabases  
WHERE name NOT IN ('master','msdb','tempdb','model','distribution')  
ORDER BY 1  

OPEN DatabaseCursor  

FETCH NEXT FROM DatabaseCursor INTO @Database  
WHILE @@FETCH_STATUS = 0  
BEGIN  

   SET @cmd = 'DECLARE TableCursor CURSOR FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' +
  table_name + '']'' as tableName FROM [' + @Database + '].INFORMATION_SCHEMA.TABLES
  WHERE table_type = ''BASE TABLE'''  

   -- create table cursor  
   EXEC (@cmd)  
   OPEN TableCursor  

   FETCH NEXT FROM TableCursor INTO @Table  
   WHILE @@FETCH_STATUS = 0  
   BEGIN  

       IF (@@MICROSOFTVERSION / POWER(2, 24) >= 9)
       BEGIN
           -- SQL 2005 or higher command
           SET @cmd = 'ALTER INDEX ALL ON ' + @Table + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ')'
           EXEC (@cmd)
       END
       ELSE
       BEGIN
          -- SQL 2000 command
          DBCC DBREINDEX(@Table,' ',@fillfactor)  
       END

       FETCH NEXT FROM TableCursor INTO @Table  
   END  

   CLOSE TableCursor  
   DEALLOCATE TableCursor  

   FETCH NEXT FROM DatabaseCursor INTO @Database  
END  
CLOSE DatabaseCursor  
DEALLOCATE DatabaseCursor 

答案 4 :(得分:0)

似乎您想使用服务器默认填充因子(0),它忽略了创建脚本中的FILLFACTOR语句。没有办法只重建索引,你必须删除并重新创建它(见here)。现在看起来并不是一种干净利落的方式,尽管现在它有点模棱两可。

答案 5 :(得分:-1)

ALTER INDEX yourindex ON table.column
REBUILD WITH (FILLFACTOR = 0); 

完成这项工作。 0等于100(见http://msdn.microsoft.com/en-us/library/ms177459.aspx),表示索引中没有留下间隙。

你必须为每个索引运行它。但重建可能需要相当长的时间。