【问题标题】:How can I speed up this sql server query?如何加快这个 sql server 查询的速度?
【发布时间】:2015-09-23 20:42:28
【问题描述】:
-- Holds last 30 valdates
create table #valdates(
    date int
)
insert into #valdates
   select distinct top (30) valuation_date 
   from tbsm.tbl_key_rates_summary 
   where valuation_date <= 20150529 
   order by valuation_date desc 

select 
    sum(fv_change), sc_group, valuation_date  
from
    (select * 
     from tbsm.tbl_security_scorecards_summary 
     where valuation_date in (select date from #valdates)) as fact
join 
    (select * 
     from tbsm.tbl_security_classification 
     where sc_book = 'UC' ) as dim on fact.classification_id = dim.classification_id
group by 
    valuation_date, sc_group

drop table #valdates

这个查询大约需要 40 秒才能返回,因为事实表有将近 1300 万行。我可以对此做些什么吗?

【问题讨论】:

  • 附带说明,如果您只保存 30 个值,我将在内存中创建一个临时表 -->DECLARE TABLE @valdates{...}。全部在内存中,以后不用担心删除,当存储过程或sql命令失去作用域时会自动删除。
  • 表变量不是“全部在内存中”,它们也像临时表一样存储在 tempdb 中,并且由于缺少统计信息/估计的行数为 1,可能会导致更大的问题。正常的临时表被删除程序结束时也是如此。
  • 在将声明@tmp 表切换为创建#tmp 表时,我们实际上大大提高了性能。临时表保存的数据越大,性能提升就越大。我会试试你的小费,谢谢。
  • @Allen,您应该至少包含一些关于表和索引是什么的想法,并且可能还包括此选择的查询计划。我的猜测是您有评估日期的索引,但它是否也包含 fv_change,或者是否进行了关键查找以找到该索引和/或分类 ID?
  • @Jamez,事实表包含 fv_change、valuation_date。 dim 表包含 sc_book、sc_group。我们按 sc_book 过滤并按 sc_group 聚合。分类 ID 连接两个表。不幸的是,这两个表的索引基本上都是伪造的。此外,valuation_date 未编入索引 :(

标签: sql-server performance join optimization


【解决方案1】:

基于没有适当的索引支持提取的事实,这可能是真正提高性能的最简单(或唯一)的选择。像这样的最有可能的索引会大大改善这种情况:

create index idx_security_scorecards_summary_1 on 
tbl_security_scorecards_summary (valuation_date, classification_id) 
include (fv_change)

当然,一切都取决于evaluation_date 和classification_id 字段的选择性有多好(=需要获取表的多大部分),并且可能以相反的顺序更好地处理字段。字段 fv_change 位于 include 部分中,因此它包含在索引结构中,因此无需从基表中获取它。

如果 SQL 必须从表中获取大量行,则包含字段会有所帮助。如果这涉及的行数很少,那么它可能根本没有帮助。就像在索引中一样,这当然会减慢插入/更新的速度,并且仅针对这种情况进行了优化,您当然也应该着眼于更大的图景。

select 的写法有点奇怪,不知道有没有什么区别,不过你也可以试试正常的方法:

select 
    sum(fact.c), dim.sc_group, fact.valuation_date  
from
    tbsm.tbl_security_scorecards_summary fact
    join tbsm.tbl_security_classification dim
        on fact.classification_id = dim.classification_id
where 
    fact.valuation_date in (select date from #valdates) and
    dim.sc_book = 'UC'
group by 
    fact.valuation_date, 
    dim.sc_group

查看“statistics io”输出应该可以让您很好地了解哪个表导致缓慢,查看查询计划以查看是否有任何奇怪的运算符可能有助于更好地了解情况。

【讨论】:

  • @Jamez,天哪,我的查询在创建索引后从 40 多秒变为 2 秒。这会影响写作性能吗?将来,我们是否需要定期重新索引,或者新插入的记录是否会自动索引?另外,当我执行“创建索引”脚本时,我究竟创建了什么?这与聚集/非聚集索引有什么不同?
  • @Allen 每个索引的每个插入(+ 可能更新)的价格都很低,因此您必须检查它的行为方式。新记录会自动添加,但所有索引都需要一些维护。如果您是(偶然的)DBA,您应该查看 Ola 的脚本:ola.hallengren.com
猜你喜欢
  • 2022-01-19
  • 2015-04-07
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 2014-10-04
  • 1970-01-01
相关资源
最近更新 更多