标签: sql-server-2008

优化大表上的连接

我试图通过访问具有约 2.5 亿条记录的表的查询来提高性能。从我对实际(未估计)执行计划的阅读来看,第一个瓶颈是如下所示的查询:

select
    b.stuff,
    a.added,
    a.value
from
    dbo.hugetable a
    inner join
    #smalltable b on a.fk = b.pk
where
    a.added between @start and @end;
Run Code Online (Sandbox Code Playgroud)

有关所涉及的表和索引的定义,请进一步向下查看。

执行计划表明#smalltable 正在使用嵌套循环,并且对hugetable 的索引扫描执行了480 次(针对#smalltable 中的每一行)。这对我来说似乎是倒退,所以我试图强制使用合并连接:

select
    b.stuff,
    a.added,
    a.value
from
    dbo.hugetable a with(index = ix_hugetable)
    inner merge join
    #smalltable b with(index(1)) on a.fk = b.pk
where
    a.added between @start and @end;
Run Code Online (Sandbox Code Playgroud)

有问题的索引(完整定义见下文)涵盖列fk(连接谓词)、added(在 where 子句中使用)和id(无用)按升序排列,并包括value

然而,当我这样做时,查询从 2 1/2 分钟到超过 9 分钟。我本来希望提示会强制更有效的连接,只对每个表进行一次传递,但显然不是。

欢迎任何指导。如果需要,提供其他信息。

更新 (2011/06/02)

重新组织表上的索引后,我取得了显着的性能进步,但是在汇总大表中的数据时遇到了新的障碍。结果是按月汇总,目前如下所示:

select
    b.stuff,
    datediff(month, …
Run Code Online (Sandbox Code Playgroud)

performance sql-server-2008

10
推荐指数
1
解决办法
4万
查看次数

从带有外部参数化“where”子句的视图中调用时,窗口函数会导致糟糕的执行计划

很久以前我遇到过这个问题,我找到了一个适合我的解决方法并忘记了它。

但是现在在 SO 上有这个问题,所以我愿意提出这个问题。

有一个视图以非常简单的方式(订单 + 订单行)连接几个表。

在没有where子句的情况下查询时,视图返回几百万行。
然而,从来没有人这样称呼它。通常的查询是

select * from that_nasty_view where order_number = 123456;
Run Code Online (Sandbox Code Playgroud)

这将返回 5m 中的大约 10 条记录。

一件重要的事情:视图包含一个窗口函数,rank(),它由始终查询视图所使用的字段精确分区:

rank() over (partition by order_number order by detail_line_number)
Run Code Online (Sandbox Code Playgroud)

现在,如果使用查询字符串中的文字参数查询此视图,完全如上所示,它会立即返回行。执行计划很好:

  • 使用索引对两个表进行索引查找order_number(返回 10 行)。
  • 在返回的微小结果上计算窗口。
  • 选择。

然而,当以参数化的方式调用视图时,事情变得很糟糕:

  • Index scan在所有表上忽略索引。返回 5m 行。
  • 巨大的加入。
  • 计算所有partitions 的窗口(大约 500k 个窗口)。
  • Filter 从 5m 中取出 10 行。
  • 选择

在涉及参数的所有情况下都会发生这种情况。它可以是 SSMS:

declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number; …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 view window-functions

10
推荐指数
2
解决办法
1926
查看次数

具有层次结构的表:创建约束以防止通过外键循环

假设我们有一个对自身有外键约束的表,如下所示:

CREATE TABLE Foo 
    (FooId BIGINT PRIMARY KEY,
     ParentFooId BIGINT,
     FOREIGN KEY([ParentFooId]) REFERENCES Foo ([FooId]) )

INSERT INTO Foo (FooId, ParentFooId) 
VALUES (1, NULL), (2, 1), (3, 2)

UPDATE Foo SET ParentFooId = 3 WHERE FooId = 1
Run Code Online (Sandbox Code Playgroud)

该表将有以下记录:

FooId  ParentFooId
-----  -----------
1      3
2      1
3      2
Run Code Online (Sandbox Code Playgroud)

在某些情况下,这种设计可能有意义(例如典型的“员工-老板-员工”关系),并且无论如何:我处于我的模式中有这种情况的情况。

不幸的是,这种设计允许数据记录中的循环,如上例所示。

那么我的问题是:

  1. 是否可以编写一个约束来检查这个?和
  2. 编写一个检查这个的约束是否可行?(如果只需要一定深度)

对于这个问题的第 (2) 部分,可能需要提及的是,我希望我的表中只有数百或在某些情况下可能有数千条记录,通常嵌套的深度不会超过大约 5 到 10 级。

附注。微软 SQL Server 2008


2012 年 3 月 14 日更新
有几个很好的答案。我现在已经接受了帮助我理解提到的可能性/可行性的那个。不过,还有其他几个很好的答案,其中一些还提供了实施建议,因此,如果您带着相同的问题来到这里,请查看所有答案;)

sql-server-2008 constraint hierarchy

10
推荐指数
3
解决办法
5228
查看次数

在此表中插入数字时如何保留前导零?

我在一个表中插入了两条记录。

create table num(id int)
insert into num values(0023)
insert into num values(23)
select * from num
Run Code Online (Sandbox Code Playgroud)

当我查询它们时,它们都显示为23. 这意味着 SQL Server 忽略前导 0。这背后的机制是什么?我如何让 SQL Server 在我插入它们时返回值(即002323)?

sql-server-2008 sql-server

10
推荐指数
2
解决办法
11万
查看次数

如何将主题应用于 SQL Server Management Studio 2008?

例如,有没有人成功地将“深色”它们应用于 SSMS 2008 的文本编辑器组件?

2005 年有一个旧技巧,它不再可操作且未升级。 http://winterdom.com/2007/10/colorschemesinsql2005managementstudio

我的眼睛会非常感谢你!干杯。

sql-server-2008 ssms

10
推荐指数
2
解决办法
2万
查看次数

为什么这个完全外部联接不起作用?

我之前使用过完全外部联接来获得我想要的结果,但也许我不完全理解这个概念,因为我无法完成应该是简单的联接。

我有 2 个表(我称之为 t1 和 t2),每个表有 2 个字段:

t1

Policy_Number Premium
101             15
102              7
103             10
108             25
111              3
Run Code Online (Sandbox Code Playgroud)

t2

Policy_Number   Loss
101              5
103              9
107              20
Run Code Online (Sandbox Code Playgroud)

我想要做的是从两个表以及 Policy_Number 中获取 Premium 和 Sum of Losses 的总和。我正在使用的代码是:

select sum(premium) Prem_Sum, sum(Loss) Loss_Sum, t1.policynumber
from t1 full outer join t2 on t1.policynumber = t2.policynumber
group by t1.policynumber
Run Code Online (Sandbox Code Playgroud)

上面的代码将返回正确的总和,但它会将在“NULL”policy_number 下没有 policy_number 匹配的所有记录分组。

我希望我的结果看起来像这样

Policy_Number    Prem_Sum    Loss_Sum
    107            NULL        20
    111              3        NULL
    101             15          5
Run Code Online (Sandbox Code Playgroud)

等等.....

我不想要显示 NULL policy_number …

sql-server-2008 join sql-server

10
推荐指数
1
解决办法
4万
查看次数

计算列中使用的标量函数,更新函数的最干净方法是什么?

我想更新我们数据库中的标量函数。此函数用于键表中的多个计算列,因此如果我尝试更新它,则会出现依赖项错误。我可以显式删除列,更新函数并重新添加列,但是,无需过多关注,这将更改列顺序并可能产生其他意想不到的后果。我想知道是否有更清洁的方法?

sql-server-2005 sql-server-2008 functions

10
推荐指数
1
解决办法
1618
查看次数

TSQL 性能 - 加入最小值和最大值之间的值

我有两张表用于存储:

  • IP 范围 - 国家/地区查找表
  • 来自不同 IP 的请求列表

IP 存储为bigints 以提高查找性能。

这是表结构:

create table [dbo].[ip2country](
    [begin_ip] [varchar](15) NOT NULL,
    [end_ip] [varchar](15) NOT NULL,
    [begin_num] [bigint] NOT NULL,
    [end_num] [bigint] NOT NULL,
    [IDCountry] [int] NULL,
    constraint [PK_ip2country] PRIMARY KEY CLUSTERED 
    (
        [begin_num] ASC,
        [end_num] ASC
    )
)

create table Request(
    Id int identity primary key, 
    [Date] datetime, 
    IP bigint, 
    CategoryId int
)
Run Code Online (Sandbox Code Playgroud)

我想获取每个国家/地区的请求细分,因此我执行以下查询:

select 
    ic.IDCountry,
    count(r.Id) as CountryCount
from Request r
left join ip2country ic 
  on r.IP between ic.begin_num …
Run Code Online (Sandbox Code Playgroud)

performance sql-server-2008 t-sql query-performance

10
推荐指数
1
解决办法
1万
查看次数

如何跟踪导致 SQL Server 崩溃的 SQL 查询

我们有一个 SQL Server 2008 数据库服务器(它恰好在 MS 故障转移群集下运行,但我认为这与此处无关)。

我们的应用程序运行 Hibernate 以进行数据库访问,自从我们最近从 v3.1 升级到 3.6 以来,我们经常遇到 SQL Server 崩溃(每 24-48 小时,但有时更频繁)。

有问题的具体问题似乎与内存有关。就在服务器崩溃之前(然后似乎由故障转移集群管理器自动重新启动),我们收到了这些错误的负载:

Error: 701, Severity: 17, State: 130.
There is insufficient system memory in resource pool 'internal' to run this query.
Run Code Online (Sandbox Code Playgroud)

也偶尔(但定期)的消息

Error: 17300, Severity: 16, State: 1. (Params:). The error is printed in terse mode because there was error during formatting. Tracing, ETW, notifications etc are skipped.
Run Code Online (Sandbox Code Playgroud)

错误:17312,严重性:16,状态:1。(参数:)。错误以简洁模式打印,因为格式化过程中出现错误。跟踪、ETW、通知等被跳过。

我还收到一些应用程序级别的错误,例如

java.sql.SQLException: A time out occurred while waiting to optimize the query. Rerun …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server crash

9
推荐指数
1
解决办法
1万
查看次数

在已提交读快照隔离 (RCSI) 下获取的共享锁

LCK_M_S在使用 RCSI时看到等待共享锁 ( )。我的理解是这不应该发生,因为SELECTs在使用 RCSI 时不需要共享锁。

我怎样才能看到共享锁?是因为外键吗?

sql-server-2008 sql-server locking snapshot-isolation

9
推荐指数
1
解决办法
1170
查看次数