Mar*_*lli 5 sql-server statistics system-tables sql-server-2014 cardinality-estimates
我正在处理一个查询,将所有直接或间接依赖于任何级别的数据库对象提供给一个名为 的表dbo.tblborder,该表严重依赖。
但是,这个问题特别与此查询的查询计划有关,因为我在查询计划中看到警告(在不同的排序运算符中)两种类型的警告,一种与溢出到 tempDB 相关,另一种与转换相关的警告数据类型和基数估计。
查询和查询计划进一步向下,在图片之后。
在处理系统对象时,如何找出需要更新统计信息的对象?
否则,如何摆脱查询计划上的这个警告?
关于数据类型转换,我可以做些什么来避免这种情况以及基数估计问题?
也许是一些跟踪标志?
它是一个 600GB 的数据库,我想找到特定表上的所有依赖项,仅第一级就显示了 325 个对象,但这不是我每天都会运行的查询。我对清除这些警告很感兴趣,但这不是生死攸关的问题。
第 1 张关于 tempdb 溢出警告的图片:
关于 tempdb 溢出警告的第二张图片:
第三个警告 - 与数据类型转换相关,可能会影响基数估计:
;WITH Radhe AS (
SELECT DISTINCT
s2.object_id,
Name=SCHEMA_NAME(S2.schema_id) + '.' + S2.Name,
ObjectType = S2.Type,
DependsOn = s1.object_id,
DependsOn_Name=SCHEMA_NAME(S1.schema_id) + '.' + S1.Name,
0 as Level
FROM sys.sysdepends DP
INNER JOIN sys.objects S1
ON S1.object_id = DP.DepID
INNER JOIN sys.objects S2
ON S2.object_id = DP.ID
WHERE S1.object_id = OBJECT_ID('DBO.tblborder')
UNION ALL
SELECT
s2.object_id,
Name=SCHEMA_NAME(S2.schema_id) + '.' + S2.Name,
ObjectType = S2.Type,
DependsOn = s1.object_id,
DependsOn_Name=s1.Name,
Level + 1
FROM sys.sysdepends DP
INNER JOIN Radhe S1
ON S1.object_id = DP.ID
INNER JOIN sys.objects S2
ON S2.object_id = DP.DepID
WHERE Level < 100
AND S1.object_id <> S2.object_id
AND S2.object_id <> OBJECT_ID('DBO.tblborder')
)
SELECT DISTINCT *
FROM Radhe
ORDER BY LEVEL DESC, DependsOn_Name
Run Code Online (Sandbox Code Playgroud)
以这种方式更新统计信息后(来自如何更新数据库系统表的统计信息):
DECLARE @TSql NVARCHAR(MAX) = ''
SELECT @TSql = @TSql + 'UPDATE STATISTICS sys.' + o.name + ' WITH FULLSCAN;' + CHAR(13) + CHAR(10)
FROM sys.objects o
WHERE o.type in ('S')
ORDER BY o.name
--Verify/test commands.
PRINT @TSql
Run Code Online (Sandbox Code Playgroud)
与 tempdb 溢出相关的警告仍然存在,但是,它们已按照下图进行了更改:
但是,对于以下警告没有说或解决任何问题:
表达式中的类型转换 (CONVERT(bigint,[Bocss2].[sys].[sysobjvalues].[value],0)) 可能会影响查询计划选择中的“CardinalityEstimate”,表达式中的类型转换 (CONVERT(bigint,[Bocss2] .[sys].[sysobjvalues].[value],0)) 可能会影响查询计划选择中的“CardinalityEstimate”
相关的Q&A How to update statistics for a database's system tables很好,但是这里好像没有完全解决我的问题,加上没有解决基数估计警告。
您看到的警告很可能来自 sys.sysdepends 视图。
如果您使用脚本编写它
EXEC sys.sp_helptext @objname = N'sys.sysdepends'
Run Code Online (Sandbox Code Playgroud)
该定义有一堆转换和其他胡说八道。
CREATE VIEW sys.sysdepends AS
SELECT
id = object_id,
depid = referenced_major_id,
number = convert(smallint,
case when objectproperty(object_id, 'isprocedure') = 1 then 1 else column_id end),
depnumber = convert(smallint, referenced_minor_id),
status = convert(smallint, is_select_all * 2 + is_updated * 4 + is_selected * 8),
deptype = class,
depdbid = convert(smallint, 0),
depsiteid = convert(smallint, 0),
selall = is_select_all,
resultobj = is_updated,
readobj = is_selected
FROM sys.sql_dependencies
WHERE class < 2
UNION ALL
SELECT -- blobtype dependencies
id = object_id, depid = object_id,
number = convert(smallint, column_id), depnumber = convert(smallint, type_column_id),
status = convert(smallint, 0), deptype = sysconv(tinyint, 1),
depdbid = convert(smallint, 0), depsiteid = convert(smallint, 0),
selall = sysconv(bit, 0), resultobj = sysconv(bit, 0), readobj = sysconv(bit, 0)
FROM sys.fulltext_index_columns
WHERE type_column_id IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
另一方面,sys.objects 相当简单。
CREATE VIEW sys.objects AS
SELECT name,
object_id,
principal_id,
schema_id,
parent_object_id,
type,
type_desc,
create_date,
modify_date,
is_ms_shipped,
is_published,
is_schema_published
FROM sys.objects$
Run Code Online (Sandbox Code Playgroud)
sys.sysdepends 的视图定义在单独查询时会导致相同的警告。
SELECT *
FROM sys.sysdepends
Run Code Online (Sandbox Code Playgroud)
一般来说,如果您想在引用系统视图或表时控制数据类型和索引并具有一定的性能调优能力,最好的办法是先将它们转储到临时表中。
| 归档时间: |
|
| 查看次数: |
1618 次 |
| 最近记录: |