Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.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_Sql Server 2008 - Fatal编程技术网

SQL查询优化

SQL查询优化,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我试图找到一个脚本,可以帮助我在我的数据库数据密度。关键是我已经弄明白了这个查询以及我需要什么,但问题是这个查询需要永远。它适用于小型DBs,但这种情况并不多见。 因此,我正在寻找一种优化或任何想法来帮助我。 剧本: DECLARE Cur CURSOR FOR SELECT DB_Name() AS DatabaseName ,s.[name] AS SchemaName ,t.[name] AS TableName ,c.[name] AS ColumnName ,'[' + DB_Name

我试图找到一个脚本,可以帮助我在我的数据库数据密度。关键是我已经弄明白了这个查询以及我需要什么,但问题是这个查询需要永远。它适用于小型DBs,但这种情况并不多见。 因此,我正在寻找一种优化或任何想法来帮助我。 剧本:

DECLARE Cur CURSOR
FOR
SELECT DB_Name() AS DatabaseName
,s.[name] AS SchemaName
,t.[name] AS TableName
,c.[name] AS ColumnName
,'[' + DB_Name() + ']' + '.[' + s.NAME + '].' + '[' + T.NAME + ']' AS FullQualifiedTableName
,d.[name] AS DataType
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types d ON c.user_type_id = d.user_type_id
 WHERE d.NAME LIKE '%int%'
OR d.NAME LIKE '%float%'
OR d.NAME LIKE '%decimal%'
OR d.NAME LIKE '%numeric%'
OR d.NAME LIKE '%real%'
OR d.NAME LIKE '%money%'
OR d.NAME LIKE '%date%'
OR d.NAME LIKE '%datetime%'

AND is_identity = 0

OPEN Cur

FETCH NEXT
FROM Cur
INTO @DatabaseName
,@SchemaName
,@TableName
,@ColumnName
,@FullyQualifiedTableName
,@DataType


WHILE @@FETCH_STATUS = 0 -- The FETCH statement was successful.
BEGIN
DECLARE @SQL VARCHAR(MAX) = NULL

SET @SQL = ' Select ''' + @DatabaseName + ''' AS DatabaseName, ''' + 
@SchemaName + ''' AS TableName,
  ''' + @TableName + ''' AS SchemaName,
  ''' + @ColumnName + ''' AS ColumnName,
  ''' + @DataType + ''' AS ColumnName,

  (Select MAX(' + @ColumnName + ') from ' + @FullyQualifiedTableName + ' with (nolock)) 
  AS MaxValue,
  (Select MIN(' + @ColumnName + ') from ' + @FullyQualifiedTableName + ' with (nolock)) 
  AS MinValue,
  (Select COUNT(*) from ' + @FullyQualifiedTableName + '   with (nolock)) 
  AS CountValue,
  (Select COUNT(*) from ' + @FullyQualifiedTableName + ' Where ' + @ColumnName + ' IS NOT NULL ) 
  AS NotNULLCount,
  (Select 0 from ' + @FullyQualifiedTableName + ') 
  AS DataDensity'

PRINT @SQL
下面的脚本将为上述声明类型的每一列提供MAX、MIN、COUNT、NotNULLCount和数据密度。但是你可以想象一个数据库有70个表,每个表有30-50列。。。。
运行此脚本将花费永远的时间

您应该始终尝试并避免使用游标,此查询将为您提供一个select查询列表,您可以复制并粘贴这些查询以获取所需的数据。注意:我已删除子选项,因为它们不是必需的:

SELECT 'Select ''' + DB_Name()  + ''' AS DatabaseName, ''' + s.Name + ''' AS SchemaName,  ''' + t.Name + ''' AS TableName,  ''' + c.Name + ''' AS ColumnName,  ''' + d.Name + ''' AS ColumnName,' +
 'MAX([' + c.Name + ']) AS MaxValue,' +
 'MIN([' + c.Name + '])  AS MinValue,' +
 'COUNT(*)  AS CountValue,' +
 'COUNT([' + c.Name + '])  AS NotNullCount,' +
  'CAST(COUNT(DISTINCT [' + c.name + ']) AS float) / COUNT([' + C.Name + '])  AS DataDensity ' +
  'from [' +  DB_Name() + '].[' + s.Name + '].[' + t.name + '] with (nolock)'
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types d ON c.user_type_id = d.user_type_id
 WHERE d.NAME LIKE '%int%'
OR d.NAME LIKE '%float%'
OR d.NAME LIKE '%decimal%'
OR d.NAME LIKE '%numeric%'
OR d.NAME LIKE '%real%'
OR d.NAME LIKE '%money%'
OR d.NAME LIKE '%date%'
OR d.NAME LIKE '%datetime%'
AND is_identity = 0
这将为您提供以下形式的select语句列表:

Select 'MyDB' AS DatabaseName, 'dbo' AS SchemaName,  'MyTable' AS TableName,  'ID' AS ColumnName,  'int' AS ColumnName,MAX([ID]) AS MaxValue,MIN([ID])  AS MinValue,COUNT(*)  AS CountValue,COUNT([ID])  AS NotNullCount,CAST(COUNT(DISTINCT [ID]) AS float) / COUNT([ID])  AS DataDensity from [MyDB].[dbo].[MyTable] with (nolock)
当然,SQL Server会为有用的列存储这些统计信息,您可以找到它正在使用的列:

EXEC SP_HELPSTATS 'MyTable', 'ALL'
然后使用返回的统计信息列表,例如:

_WA_Sys_00000014_004FB3FB   ID
要获取实际统计信息,请使用:

DBCC SHOW_STATISTICS('MyTable','_WA_Sys_00000002_004FB3FB')
这将返回如下数据:

Name    Updated Rows    Rows Sampled    Steps   Density Average key length  String Index    Filter Expression   Unfiltered Rows
_WA_Sys_00000002_004FB3FB   Jan  8 2017  8:01PM 16535   16535   200 0.2493151   4.459389    NO  NULL    16535

另一行集显示值的直方图

您可以使用以下命令自动生成这些
DBCC
命令:

SELECT  'DBCC SHOW_STATISTICS([' + OBJECT_NAME(s.object_Id) + '],''' +  s.Name + ''')'
FROM sys.stats s 
  INNER JOIN sys.stats_columns sc
    ON s.object_id = sc.object_id AND s.stats_id = sc.stats_id
  INNER JOIN sys.columns c
    ON sc.object_id = c.object_id AND sc.column_id = c.column_id
WHERE s.Name LIKE '_WA%'
ORDER BY s.stats_id, sc.column_id;

寻求性能帮助的问题应包括涉及的表的DDL、DML以及测试数据。如果测试数据很大,请尝试为表编写架构和统计数据脚本(
右键单击数据库->生成脚本->选择特定的数据库对象->在下一个屏幕中选择高级并选择脚本统计)
并将其粘贴到问题中..根据此信息,任何人都可以复制您面临的相同问题。粘贴服务器版本也有帮助,这实际上是一个很好的解决方案,但尽管我需要一个光标来执行表中的所有select语句,因为在最后,结果表是我需要的
SELECT  'DBCC SHOW_STATISTICS([' + OBJECT_NAME(s.object_Id) + '],''' +  s.Name + ''')'
FROM sys.stats s 
  INNER JOIN sys.stats_columns sc
    ON s.object_id = sc.object_id AND s.stats_id = sc.stats_id
  INNER JOIN sys.columns c
    ON sc.object_id = c.object_id AND sc.column_id = c.column_id
WHERE s.Name LIKE '_WA%'
ORDER BY s.stats_id, sc.column_id;