帽桌 SELECT DISTINCT ta.account_num as 'Account', tl.billing_year as 'Year', tl.billing_month as 'Month', ta.bill_date as 'Bill Date', DATEDIFF(DD, cast(cast(tl.billing_year as varchar(4)) + right('0' + cast(tl.billing_month as varchar(2)), 2) + right('0' + (case when billing_month in (4,6,9,11) and bill_date > 30 then '30' when billing_month = 2 and bill_date > 28 then '28' else cast(bill_date as varchar(2)) end), 2) as datetime), GETDATE()) as 'Past', DATEADD(Day,10,d) as 'To be Loaded Before', p.provider_name as 'Provider', c.client as 'Client', tip.invoice_load_type as 'Load Type' FROM tm_invoice_load tl JOIN tm_client c ON tl.client_id = c.client_id JOIN tm_client_account ta ON (ta.account_num = tl.account_num or ta.pilot = tl.account_num) --This spot right here AND ta.status_id = 1 AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot) --AND ta.invoice_load_type_id = 2 JOIN provider p ON p.id_provider = ta.id_provider JOIN tm_invoice_load_type tip ON tip.invoice_load_type_id = ta.invoice_load_type_id JOIN tm_calendar cal ON Convert(date, cal.d) = Convert(date, tl.entry_dt) WHERE tl.status_id = 2 AND NOT EXISTS (SELECT * FROM tm_invoice_load xx WHERE xx.billing_year = tl.billing_year AND xx.billing_month = tl.billing_month AND xx.status_id = 1 AND (xx.account_num = ta.account_num OR xx.account_num = ta.pilot)) ORDER BY c.client, p.provider_name, ta.account_num, tl.billing_year, tl.billing_month

帽桌 SELECT DISTINCT ta.account_num as 'Account', tl.billing_year as 'Year', tl.billing_month as 'Month', ta.bill_date as 'Bill Date', DATEDIFF(DD, cast(cast(tl.billing_year as varchar(4)) + right('0' + cast(tl.billing_month as varchar(2)), 2) + right('0' + (case when billing_month in (4,6,9,11) and bill_date > 30 then '30' when billing_month = 2 and bill_date > 28 then '28' else cast(bill_date as varchar(2)) end), 2) as datetime), GETDATE()) as 'Past', DATEADD(Day,10,d) as 'To be Loaded Before', p.provider_name as 'Provider', c.client as 'Client', tip.invoice_load_type as 'Load Type' FROM tm_invoice_load tl JOIN tm_client c ON tl.client_id = c.client_id JOIN tm_client_account ta ON (ta.account_num = tl.account_num or ta.pilot = tl.account_num) --This spot right here AND ta.status_id = 1 AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot) --AND ta.invoice_load_type_id = 2 JOIN provider p ON p.id_provider = ta.id_provider JOIN tm_invoice_load_type tip ON tip.invoice_load_type_id = ta.invoice_load_type_id JOIN tm_calendar cal ON Convert(date, cal.d) = Convert(date, tl.entry_dt) WHERE tl.status_id = 2 AND NOT EXISTS (SELECT * FROM tm_invoice_load xx WHERE xx.billing_year = tl.billing_year AND xx.billing_month = tl.billing_month AND xx.status_id = 1 AND (xx.account_num = ta.account_num OR xx.account_num = ta.pilot)) ORDER BY c.client, p.provider_name, ta.account_num, tl.billing_year, tl.billing_month,join,sql-server-2008-r2,query-optimization,Join,Sql Server 2008 R2,Query Optimization,你能创建索引,看看是否有帮助吗? 如果查询计划显示,而不是继续使用tm\u client\u account上的表扫描,则将WITH(INDEX=idx\u test)添加到JOIN子句中,然后重试 如果所有这些都没有真正减少查询所需的时间,那么您可以尝试通过索引视图对内容进行预筛选。 警告:请记住,在表上执行INSERT/UPDATE/DELETE操作时,向表中添加索引会导致性能下降;在其上添加过滤视图将加倍!如果此表中的数据(非常)不稳定,则索引和/或视图可能会使系统的其他部分明显变慢。再说

你能创建索引,看看是否有帮助吗? 如果查询计划显示,而不是继续使用
tm\u client\u account
上的表扫描,则将
WITH(INDEX=idx\u test)
添加到
JOIN
子句中,然后重试

如果所有这些都没有真正减少查询所需的时间,那么您可以尝试通过索引视图对内容进行预筛选。 警告:请记住,在表上执行INSERT/UPDATE/DELETE操作时,向表中添加索引会导致性能下降;在其上添加过滤视图将加倍!如果此表中的数据(非常)不稳定,则索引和/或视图可能会使系统的其他部分明显变慢。再说一遍,SQL在这方面做得相当好,所以唯一确定的方法是通过测试

步骤1:创建视图

CREATE VIEW v_test_tm_client_account_filtered
WITH SCHEMABINDING
AS
SELECT id_client_account, -- I am assuming that there is an identity-field like this on the table, adapt as needed!
       account_num, 
       pilot,
       bill_date, 
       id_provider,
       invoice_load_type_id
  FROM tm_client_account ta
 WHERE status = 1
   AND ta.status_id = 1
   AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot)
 --AND ta.invoice_load_type_id = 2
步骤3:调整查询以使用视图而不是直接使用表

  JOIN tm_client_account ta 
    ON (ta.account_num = tl.account_num or ta.pilot = tl.account_num) --This spot right here
   AND ta.status_id = 1
   AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot)
 --AND ta.invoice_load_type_id = 2

然后再次运行查询

如果有人遇到类似的问题,我唯一能让它更快的方法就是告诉查询不要锁定数据。我不知道这有什么帮助,但它将查询时间缩短了不到一半。这对返回的数据没有影响,显式排序使其不可见

select distinct 
    ta.account_num as 'Account', 
    tl.billing_year as 'Year', 
    tl.billing_month as 'Month', 
    ta.bill_date as 'Bill Date', 
    DATEDIFF(DD, cast(cast(tl.billing_year as varchar(4)) + right('0' + cast(tl.billing_month as varchar(2)), 2) + right('0' + (case when billing_month in (4,6,9,11) and bill_date > 30 then '30' when billing_month = 2 and bill_date > 28 then '28' else cast(bill_date as varchar(2)) end), 2) as datetime), GETDATE()) as 'Past', 
    DATEADD(Day,10,d) as 'To be Loaded Before',
    p.provider_name as 'Provider', 
    c.client as 'Client',
    tip.invoice_load_type as 'Load Type'
from 
    tm_invoice_load tl

with (nolock) --This accelerates the select statement!

inner join 
    tm_client c on tl.client_id = c.client_id
[...]

同时添加了一个计算列,该查询仍然从7-8秒下降到2.5-3.5秒。同样,我也不知道为什么,但这很有帮助。这可能也会对其他人有所帮助。

如果有人遇到类似问题,我唯一能加快速度的方法就是告诉查询不要锁定数据。我不知道这有什么帮助,但它将查询时间缩短了不到一半。这对返回的数据没有影响,显式排序使其不可见

select distinct 
    ta.account_num as 'Account', 
    tl.billing_year as 'Year', 
    tl.billing_month as 'Month', 
    ta.bill_date as 'Bill Date', 
    DATEDIFF(DD, cast(cast(tl.billing_year as varchar(4)) + right('0' + cast(tl.billing_month as varchar(2)), 2) + right('0' + (case when billing_month in (4,6,9,11) and bill_date > 30 then '30' when billing_month = 2 and bill_date > 28 then '28' else cast(bill_date as varchar(2)) end), 2) as datetime), GETDATE()) as 'Past', 
    DATEADD(Day,10,d) as 'To be Loaded Before',
    p.provider_name as 'Provider', 
    c.client as 'Client',
    tip.invoice_load_type as 'Load Type'
from 
    tm_invoice_load tl

with (nolock) --This accelerates the select statement!

inner join 
    tm_client c on tl.client_id = c.client_id
[...]

同时添加了一个计算列,该查询仍然从7-8秒下降到2.5-3.5秒。同样,我也不知道为什么,但这很有帮助。它可能也会帮助其他人。

对于性能问题,您必须包括@JuanCarlosOropeza,这里有什么特别的方法可以最好地展示它吗?根据您链接到的帖子,这里有很多,我想知道这里更喜欢哪一个,因为我以前没有问过任何这样的问题…关于查询计划,理想情况下,您可以在SqlSentry plan Explorer中运行查询(免费即可),然后执行文件/另存为。。并将其另存为.queryanalyis文件。拉上拉链,在某个地方分享。如果这不是一个选项,您可以在SSMS中执行相同的操作;右键单击查询计划并选择“另存为…”。。。。同样有效,但保留的信息较少。无论如何,从屏幕截图上看,似乎有一个特定的连接消耗了85%的成本,当你浏览它时,检查弹出窗口以获取更多信息。@deroby我实际上在代码块中添加了一条注释,指出是哪个
连接
导致了问题(
tm\U client\U帐户)(ta.account\u num=tl.account\u num或ta.pilot=tl.account\u num)
)…我已经做到了这一点,但我不知道如何以一种更有效的方式来改变它…对于性能问题,你必须包括@JuanCarlosOropeza,这里有什么特别的方式来最好地展示它吗?根据你链接到的帖子,有很多,我想知道这里更喜欢哪个,因为我以前没有问过这样的问题关于查询计划,理想情况下,您可以在SqlSentry计划资源管理器中运行查询(免费即可),然后执行File/Save as..并将其另存为.queryanalyis File.Zip并在某处共享。如果这不是一个选项,您可以在SSMS中执行相同的操作;右键单击查询计划并选择“另存为…”也可以工作,但保留的信息较少。无论如何,从屏幕截图上看,似乎有一个特定的连接消耗了85%的成本,请查看弹出窗口以获取更多信息nfo当你浏览时。@deroby我实际上在代码块中放了一条注释,指出是哪个
join
引起了问题(
tm\u client\u account ta on(ta.account\u num=tl.account\u num或ta.pilot=tl.account\u num)
)…我做到了这一点,但我不确定如何以更高效的方式更改它…在最终有足够的时间测试所有建议的调整后,我非常惊讶地发现原始查询仍然比这里的任何查询都要快(公平地说,我怀疑服务器总负载是最大的因素,比这些查询中的任何内容都要大)。在7秒的时间跨度内,差异通常不到200毫秒。奇怪的是,您为可读性而进行的重新组织(这应该不会产生影响)使查询时间增加了几乎一致的一秒。我使用了此查询的4个版本进行测试以比较选项,当出现差异时,原始版本仍然是最快的。在fairne中第一个索引(在tm_客户_账户上)用于所有测试,但我注意到它本身做得很少(一致增益小于200ms)。RDBMS有时非常类似于黑魔法=)如果你真的需要压缩这7秒钟,我建议让QueryPlan Explorer试一试,看看它是否显示了任何值得进一步调整的地方。另一种选择可能是先只连接一些表,将结果转储到临时表中,也许索引所述临时表,然后连接所有其他表。判断哪些表要“预连接”是很棘手的。这在很大程度上取决于您对手头数据的了解程度,以及您对事物如何相互连接的估计程度。以及其他负载数据是否也是如此。祝您好运!在终于有足够的时间测试所有建议的调整后,我非常惊讶地发现原始查询仍然比这里的任何查询都要快(公平地说,我怀疑服务器总负载是最大的因素,比这些查询中的任何内容都要大)。在7秒钟的时间跨度内,差异通常小于200毫秒。奇怪的是,您为可读性而进行的重新组织(这本应不会产生影响)使查询时间增加了几乎一致的一秒。我使用了此查询的4个版本进行测试,以比较选项,当出现差异时,
CREATE VIEW v_test_tm_client_account_filtered
WITH SCHEMABINDING
AS
SELECT id_client_account, -- I am assuming that there is an identity-field like this on the table, adapt as needed!
       account_num, 
       pilot,
       bill_date, 
       id_provider,
       invoice_load_type_id
  FROM tm_client_account ta
 WHERE status = 1
   AND ta.status_id = 1
   AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot)
 --AND ta.invoice_load_type_id = 2
CREATE UNIQUE CLUSTERED INDEX idx_test ON v_test_tm_client_account_filtered (account_num, pilot, id_client_account)
  JOIN tm_client_account ta 
    ON (ta.account_num = tl.account_num or ta.pilot = tl.account_num) --This spot right here
   AND ta.status_id = 1
   AND (ta.pilot IS NULL OR ta.account_num <> ta.pilot)
 --AND ta.invoice_load_type_id = 2
  JOIN v_test_tm_client_account_filtered ta 
    ON ta.account_num = tl.account_num 
    OR ta.pilot       = tl.account_num
select distinct 
    ta.account_num as 'Account', 
    tl.billing_year as 'Year', 
    tl.billing_month as 'Month', 
    ta.bill_date as 'Bill Date', 
    DATEDIFF(DD, cast(cast(tl.billing_year as varchar(4)) + right('0' + cast(tl.billing_month as varchar(2)), 2) + right('0' + (case when billing_month in (4,6,9,11) and bill_date > 30 then '30' when billing_month = 2 and bill_date > 28 then '28' else cast(bill_date as varchar(2)) end), 2) as datetime), GETDATE()) as 'Past', 
    DATEADD(Day,10,d) as 'To be Loaded Before',
    p.provider_name as 'Provider', 
    c.client as 'Client',
    tip.invoice_load_type as 'Load Type'
from 
    tm_invoice_load tl

with (nolock) --This accelerates the select statement!

inner join 
    tm_client c on tl.client_id = c.client_id
[...]