tsql 查询分析器:如何降低“成本”?
Posted
技术标签:
【中文标题】tsql 查询分析器:如何降低“成本”?【英文标题】:tsql query analyzer : how do you reduce "cost"? 【发布时间】:2009-05-07 19:23:09 【问题描述】:我正在对以下查询运行 sql 分析器
SELECT bl.Invoice_Number, bl.Date_Invoice, ti.TranNo, bt.Description,
CONVERT(decimal(15,2), bl.Invoice_Amount) AS Invoice_Amount, co.Company_ID, co.Account_Nbr,
isnull(bl.Reference,' ') as Reference, bl.Billing_Log_RecID AS BillingKey
FROM [CONN.domain.NET].cwwebapp.dbo.Billing_Log bl
LEFT JOIN [App].dob.tarInvoice ti
ON bl.Invoice_Number = dbo._fnStripLeadZeros(ti.TranNo)
INNER JOIN [CONN.domain.NET].cwwebapp.dbo.Billing_Type bt
ON bl.Billing_Type_ID = bt.Billing_Type_ID
LEFT JOIN [CONN.domain.NET].cwwebapp.dbo.Company co
ON bl.Company_RecID = co.Company_RecID
WHERE bl.Date_Invoice >= '2009-05-05'
AND ti.TranNo IS NULL
AND bl.Invoice_Amount <> 0
AND bl.Billing_Type_ID <> 'D'
AND bl.Billing_Type_ID <> 'P'
-- AND bl.Billing_Type_ID <> 'M'
Order By bl.Invoice_Number
查询在 [App] 服务器上运行并连接到 [Conn] sql server 进行连接 图表告诉我
remote query cost : 62%
customered index scan [App].[dbo].tarInvoice.[PK__... Cost : 34%
此查询需要 2 分钟才能运行。关于如何弄清楚如何更有效地运行的任何想法?我猜这与连接到同一网络上的另一个 sql 服务器有关。
提前致谢。
【问题讨论】:
@phill 说“你怎么知道怎么做?”,经验,经验,经验,还有这个提示:当查询运行缓慢时,请执行以下操作:运行 SET ShowPlan_All ON,然后运行您的查询,查看单词“scan”的输出。你的问题就在那里。 “扫描” = 触摸每一行(表格或索引)。您想“扫描”电话簿还是使用索引?修改时不能使用索引,所以我建议你不要修改它。您可以修改与索引进行比较的搜索字符串(bl.Invoice_Number)并仍然使用索引 【参考方案1】:您正在对 tarInvoice 聚集索引进行完整扫描(触摸每个索引条目),看看您是否可以删除函数调用 dbo._fnStripLeadZeros(ti.TranNo) 以便它使用索引。
可能在 bl.Invoice_Number 上添加前导零并加入未更改的 ti.TranNo
编辑
添加不带前导零的计算列并添加索引:
ALTER TABLE dbo.tarInvoice ADD TranNoZeroFree AS Convert(int,TranNo) PERSISTED
GO
CREATE NONCLUSTERED INDEX IX_tarInvoice_TranNoZeroFree ON dbo.tarInvoice (TranNoZeroFree) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
【讨论】:
成功了..你怎么知道怎么做?你能推荐任何文章来阅读这个吗? @phill 说“你怎么知道怎么做?”,经验,经验,经验,还有这个提示:当查询运行缓慢时,请执行以下操作:运行 SET ShowPlan_All ON,然后运行您的查询,查看单词“scan”的输出。你的问题就在那里。 “扫描” = 触摸每一行(表格或索引)。您想“扫描”电话簿还是使用索引?修改时不能使用索引,所以我建议你不要修改它。您可以修改与索引进行比较的搜索字符串 (bl.Invoice_Number) 并仍然使用该索引。 @phil,只要你有一个处于连接条件的函数,这都是一件坏事。函数对于性能的影响可能与游标一样糟糕,应尽可能避免使用。 我回去检查了输出,结果不正确,我需要匹配前导零。 @Phil,bl.Invoice_Number 和 ti.TranNo 的数据类型是什么,格式如何?【参考方案2】:尝试将远程服务器添加为linked server。
【讨论】:
查询似乎表明他已经在使用链接服务器?名称为 [CONN.domain.NET] 他使用 4 部分命名,除非可以命名链接服务器 [CONN.domain.NET]。 四部分表名的第一部分是远程服务器,对吧?第二部分是在本地服务器上切换数据库。像 server.database.schema.table。 我不认为数据库是链接的..我该如何检查?【参考方案3】:只使用了一个本地表,因此您可以将更多查询转移到另一台服务器:
select *
from openquery([CONN.domain.NET],'
SELECT bl.Invoice_Number, bl.Date_Invoice, ti.TranNo, bt.Description,
CONVERT(decimal(15,2), bl.Invoice_Amount) AS Invoice_Amount,
co.Company_ID, co.Account_Nbr, isnull(bl.Reference,'' '') as Reference,
bl.Billing_Log_RecID AS BillingKey
FROM cwwebapp.dbo.Billing_Log bl
INNER JOIN cwwebapp.dbo.Billing_Type bt
ON bl.Billing_Type_ID = bt.Billing_Type_ID
LEFT JOIN cwwebapp.dbo.Company co
ON bl.Company_RecID = co.Company_RecID
WHERE bl.Date_Invoice >= ''2009-05-05''
AND bl.Invoice_Amount <> 0
AND bl.Billing_Type_ID <> ''D''
AND bl.Billing_Type_ID <> ''P''
') remote
LEFT JOIN tarInvoice ti
ON remote.Invoice_Number = dbo._fnStripLeadZeros(ti.TranNo)
WHERE ti.TranNo IS NULL
Order By remote.Invoice_Number
不确定确切的语法,只是试图指出可能的改进方向。
【讨论】:
我尝试执行上述操作并收到返回的消息“无法完成延迟准备”不知道这是什么意思.. 对不起,我是这个的新手 表示openquery() 的查询参数不是正确的sql。您可以在另一台服务器上尝试以获取更详细的消息,但由于 KM 已经解决了问题,这有点没有实际意义 :) 是的,但我仍然想学习不同的方法来做同样的事情。这仍然是一个非常有趣的方法【参考方案4】:我还建议,如果您必须在查询中转换数据,例如: 转换(十进制(15,2),bl.Invoice_Amount) 那么您需要考虑重构您的数据库以使用正确的数据类型。
【讨论】:
以上是关于tsql 查询分析器:如何降低“成本”?的主要内容,如果未能解决你的问题,请参考以下文章
降低表值函数的成本 - 查询计划中的 XML 阅读器 - 如何?