Sql server 2008 使用SSI以高性能执行操作

Sql server 2008 使用SSI以高性能执行操作,sql-server-2008,ssis,Sql Server 2008,Ssis,我正在尝试根据我的CDR表中的呼叫详细记录创建用户网络 为了让事情变得简单,让我们假设我有CDR表: CDRid UserAId UserBId 有超过1亿条记录,所以这个表相当大 我创建了user2user表: UserAId UserBId NumberOfConnections 然后使用curos遍历表中的每一行,然后生成select语句: 如果在user2user表中有一个记录,其中包含来自CDR记录的UserAId=UserAId和来自CDR记录的UserBId=UserBId,则

我正在尝试根据我的CDR表中的呼叫详细记录创建用户网络

为了让事情变得简单,让我们假设我有CDR表:

CDRid
UserAId
UserBId
有超过1亿条记录,所以这个表相当大

我创建了user2user表:

UserAId
UserBId
NumberOfConnections
然后使用curos遍历表中的每一行,然后生成select语句:

如果在user2user表中有一个记录,其中包含来自CDR记录的UserAId=UserAId和来自CDR记录的UserBId=UserBId,则增加NumberOfConnections

否则,插入NumebrOfConnections=1的行

这项任务非常简单,正如我所说的那样,使用游标工作,但性能非常差(在我的计算机上估计的时间约为60小时)

我听说SQLServerIntegrationServices在我们谈论如此大的表时有更好的性能

问题是我不知道如何定制SSIS包来创建这样的任务

如果有人知道如何帮助我,有什么好的资源等,我会非常感激

也许还有其他更好的解决方案可以让它更快地工作。我使用了索引和变量表等,性能仍然很好

谢谢你的帮助

附言

这是我写的脚本,执行需要40-50小时

DECLARE CDR_cursor CURSOR FOR 
SELECT CDRId, SubscriberAId, BNumber 
FROM dbo.CDR

OPEN CDR_cursor;

FETCH NEXT FROM CDR_cursor 
INTO @CdrId, @SubscriberAId, @BNumber;

WHILE @@FETCH_STATUS = 0

BEGIN
--这里我检查是否有一个用户拥有这个号码(因为在CDR中我只有SubscriberAId和BNumber,所以我需要检查这是哪一个用户(我只有来自的用户) --网络,因此每次我找不到该用户时,我都会添加一个位于外部网络的用户)

这是你需要的吗

select 
UserAId, UserBId, count(CDRid) as count_connections
from cdr
group by UserAId, UserBId
这是你需要的吗

select 
UserAId, UserBId, count(CDRid) as count_connections
from cdr
group by UserAId, UserBId

SSIS的一点是它可能不会比光标快很多。它做的事情基本上是一样的:逐条记录读取表记录,处理记录,然后移动到下一条记录。SSIS中有一些高级技术,如数据输入分片,如果您有重型硬件,这会有所帮助,但没有重型硬件会很慢的

更好的解决方案是编写INSERT和UPDATE语句,以提供所需的内容。这样,您就可以更好地利用数据库上的索引。它们看起来像:

WITH SummaryCDR AS (UserAId, UserBId, Conns) AS
(
SELECT UserAId, UserBId, COUNT(1) FROM CDR
GROUP BY UserAId, UserBId)    
UPDATE user2user
SET NumberOfConnections = NumberOfConnections + SummaryCDR.Conns
FROM SummaryCDR
WHERE SummaryCDR.UserAId = user2user.UserAId
AND SummaryCDR.UserBId = user2user.UserBId

INSERT INTO user2user (UserAId, UserBId, NumberOfConnections)
SELECT CDR.UserAId, CDR.UserBId, Count(1)
FROM CDR
LEFT OUTER JOIN user2user
ON user2user.UserAId = CDR.UserAId
AND user2user.UserBId = CDR.UserBId
WHERE user2user.UserAId IS NULL

GROUP BY CDR.UserAId, CDR.UserBId

(注意:我没有时间测试这段代码,你必须自己调试)

SSIS的优点是它可能不会比光标快多少。它几乎做了同样的事情:逐条记录读取表记录,处理记录,然后移动到下一条记录。SSIS中有一些高级技术,如数据输入分片,如果您有重型硬件,但没有这会很慢的

更好的解决方案是编写INSERT和UPDATE语句,以提供所需的内容。这样,您就可以更好地利用数据库上的索引。它们看起来像:

WITH SummaryCDR AS (UserAId, UserBId, Conns) AS
(
SELECT UserAId, UserBId, COUNT(1) FROM CDR
GROUP BY UserAId, UserBId)    
UPDATE user2user
SET NumberOfConnections = NumberOfConnections + SummaryCDR.Conns
FROM SummaryCDR
WHERE SummaryCDR.UserAId = user2user.UserAId
AND SummaryCDR.UserBId = user2user.UserBId

INSERT INTO user2user (UserAId, UserBId, NumberOfConnections)
SELECT CDR.UserAId, CDR.UserBId, Count(1)
FROM CDR
LEFT OUTER JOIN user2user
ON user2user.UserAId = CDR.UserAId
AND user2user.UserBId = CDR.UserBId
WHERE user2user.UserAId IS NULL

GROUP BY CDR.UserAId, CDR.UserBId

(注意:我没有时间测试这段代码,你必须自己调试)

你能把条件更新/插入分解成两个单独的语句并去掉游标吗


对所有空行执行INSERT,对所有非空行执行UPDATE。

能否将条件UPDATE/INSERT分解为两个单独的语句,并去掉光标


对所有空行执行INSERT操作,对所有非空行执行更新操作。

为什么要考虑对这样大小的表进行逐行处理?您知道可以使用合并语句和INSERT或UPDATE,速度会更快。或者,您可以编写更新操作,将所有需要更新的行插入到一个基于集合的语句和insert可在基于集合的语句中不存在行时插入所有行

停止使用values子句,改为使用带连接的insert。更新也是如此。如果您需要额外的复杂性,case stamenet可能会满足您的所有需要

通常情况下,不要考虑逐行处理。如果可以为光标编写select,则可以编写基于集合的语句来完成99.9%的工作


您可能仍然需要一个表如此大的游标,但它可以处理成批数据(例如,一次处理1000条记录)没有一个可以按行运行ro。

为什么您甚至考虑在这样大小的表上逐行处理?您知道可以使用合并语句和插入或更新,这样会更快。或者您可以编写更新,将需要更新的所有行插入到一个基于集合的语句中,并在不存在行时插入所有行在一个基于集合的语句中

停止使用values子句,改为使用带连接的insert。更新也是如此。如果您需要额外的复杂性,case stamenet可能会满足您的所有需要

通常情况下,不要考虑逐行处理。如果可以为光标编写select,则可以编写基于集合的语句来完成99.9%的工作


您可能仍然需要一个表如此大的游标,但它可以处理成批数据(例如,一次处理1000条记录)不是一个逐行运行ro的方法。

是的,但实际操作要复杂得多,我想知道如何使用ssis对每一行执行迭代并将结果插入表中。这只是一个简单的示例,但无论如何,谢谢您可以将迭代和插入保留在存储过程中,然后从ssis执行。您是否考虑使用itera使用SSI遍历行您的性能会提高吗?是的,但实际操作相当复杂,我想知道如何使用SSI遍历每行并将结果插入表中。这只是一个简单的示例,但无论如何,谢谢您可以将迭代和插入保留在存储过程中,然后从SSI执行。我们您是否认为如果使用SSI遍历行,您的性能会有所提高?问题是我只有一个AuserId成员可以调用