2009-09-25 80 views
0

我试图加载从Oracle到SQL Server数据的性能(对不起,之前不写这个)提高大型缓慢dataloading查询

我有一个表(实际上是具有不同表中数据的视图)与至少有100万条记录。我以这样的方式设计我的包,使我具有业务逻辑的功能,并直接在选择查询中调用它们。

例:

X1(id varchar2) 
x2(id varchar2, d1 date) 
x3(id varchar2, d2 date) 

Select id, x, y, z, decode (.....), x1(id), x2(id), x3(id) 
FROM Table1 

注:我的表有20列,我呼吁ATLEAST 6-7列的5种不同的功能。 还有一些功能比较审计表中传递的参数和执行逻辑

我该怎样才能提高查询性能还是有更好的方法来做到这一点

我试图做它在C#代码,但最初选择的记录对于数据集来说足够大,并且我会发现内存异常。

我的功能做选择,然后例如进行逻辑:

Function(c_x2, eid) 

    Select col1 
    into p_x1 
    from tableP 
    where eid = eid; 

    IF (p_x1 = NULL) THEN 
    ret_var := 'INITIAL'; 
    ELSIF (p_x1 = 'L') AND (c_x2 = 'A') THEN 
    ret_var:= 'RL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'RL', eid, 'PackageProcName'); 

    ELSIF (p_x1 = 'A') AND (c_x2 = 'L') THEN 
    ret_var := 'GL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'GL', eid, 'PackgProcName'); 

    END IF; 

RETURN ret_var; 
+0

你会为所有1,000,000条记录运行这些函数吗?是的,这需要一些时间来运行 - 当然不是毫秒。你的期望是什么? – Guy 2009-09-25 14:02:09

+0

我从来没有说我想要毫秒,它运行1小时..所以我想改善(提高)表现我说...我没有写我想让它在一眨眼之间完成 – 2009-09-25 14:21:48

+1

看到我的最新回答编辑 – 2009-09-25 17:32:47

回答

0

首先,您需要找到性能问题的实际位置。然后你可以看看试图解决它。

  1. 视图的性能如何?在没有任何函数调用的情况下执行 需要多长时间?尝试运行命令

    它表现如何?这需要1分钟还是1小时?

     
    create table the_view_table 
    as 
    select * 
    from the_view; 
    
  2. 函数的功能如何?根据描述,您正在进行大约500万次函数调用。他们最好相当高效!功能也定义为deterministic。如果使用关键字deterministic定义功能,则Oracle有机会优化掉某些呼叫。

  3. 有没有减少函数调用次数的方法?一旦视图被评估并且有数百行数据可用,函数将被调用。但都是来自查询最高级别的输入值?函数调用是否可以嵌入到较低级别的视图中。考虑以下两个查询。哪个会更快?

    select 
        f.dim_id, 
        d.dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from large_fact_table f 
    join small_dim_table d on (f.dim_id = d.dim_id)
    select 
        f.dim_id, 
        d.dim_col_1, 
        d.dim_col_2 
    from large_fact_table f 
    join (
        select 
        dim_id, 
        dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from small_dim_table) d on (f.dim_id = d.dim_id)

    理想的情况下,它调用函数的次数更少第二个查询应该可以跑得快一点。

性能问题可能是在这些地方,直到你调查这个问题,这将是很难知道从哪里指导的调优工作。

+0

谢谢,我再次通过功能和查询,并会看到我如何可以避免不必要的电话.. – 2009-09-25 15:47:18

0

创建你的桌子上的排序国际展览中心。

Introduction to SQL Server Indizes,其他RDBMS是相似的。因为你编辑你的问题

编辑:

使用视图更是次优,从中查询单行时尤其如此。我认为你的“业务功能”实际上就像存储过程一样?

正如其他人所建议的,在SQL中总是要根据设置。我假定你已经这样做了,因此我开始使用索引。

0

几个秘诀:

  • 所有记录不加载到RAM中,而是由一个处理这些之一。
  • 尽量在客户端上运行尽可能多的功能。数据库执行用户定义函数的速度非常慢。
  • 如果您需要连接两个表,有时可能会在客户端上创建两个连接。通过连接1获取数据主数据,使用连接2获取审计数据。以相同的方式为两个连接排序数据,以便您可以从两个连接中读取单个记录并执行您所需的任何操作。
  • 如果您的函数始终为相同的输入返回相同的结果,请使用计算列或实例化视图。数据库将运行一次函数并将其保存在某个表中。那会让INSERT变慢,但是SELECT很快。
+0

我写了相同的代码在c#中使用datareader我得到每一行,并在C#中执行逻辑,然后插入...这也需要很多时间... 我使用的函数带参数和执行一些逻辑:如比较,然后计算日期或其他数据... 我没有在我的查询中使用任何连接 – 2009-09-25 13:40:24

+3

(-1)使用基于集合的SQL - 不按记录记录。尝试使用快速的原生SQL函数。使用数据库作为数据库 - 它是为连接/更新/查询而构建的。不要以为你可以用我们的编程技巧重新编写数据库。 – Guy 2009-09-25 14:00:22

+0

我正在做C#中的功能不是在SQL中,如果我尝试加载一切在我的记忆中一次,它是thorwing outof内存异常,这就是为什么我使用datareader ...我知道什么数据库建... ...我试图得到答案,并学习不重写数据库plz ... – 2009-09-25 14:20:23

4

我得到的每一行和C#进行 逻辑,然后插入

如果从SELECT可能INSERT:

INSERT INTO YourNewTable 
     (col1, col2, col3) 
    SELECT 
     col1, col2, col3 
     FROM YourOldTable 
     WHERE .... 

这将运行显著快而不是单个查询,然后循环遍历结果集并对每行都进行INSERT。

编辑作为OP问题编辑:

你应该能够取代函数调用普通的SQL查询中。使用LEFT JOIN表P模拟“初始”,可以使用CASE计算“RL”或“GL”。基于OP最近的评论

编辑

,因为您从Oracle数据加载到SQL Server中,这是我会做什么:大多数人,可以帮助已经转移上,而不会再次读取这个问题,所以在你说:1)你需要将数据从Oracle(版本)加载到SQL Server版本2)中打开一个新问题,目前你正在从一个查询处理C#中的每一行并将其插入到SQL Server中,是慢的。和所有其他细节。将数据批量加载到SQL Server有很多更好的方法。至于这个问题,你可以接受一个答案,在你解释你需要提出一个新问题时回答自己,或者让它不被接受。

+0

插入选择将无法为我工作,因为我正在加载oracle表到sql服务器 而我不能做插入审计,如果我使用CASE – 2009-09-25 15:26:58

+1

哇!不会_i'm加载到sql server_的oracle表已经是你在问题中的东西?靠近顶部? – 2009-09-25 15:37:33

2

我的建议是你做而不是使用函数,然后在其他SELECT语句中调用它们。这:

SELECT t.id, ... 
     x1(t.id) ... 
    FROM TABLE t 

...相当于:

SELECT t.id, ... 
     (SELECT x.column FROM x1 x WHERE x.id = t.id) 
    FROM TABLE t 

封装不SQL工作中使用C#/等时等。虽然该方法使维护更容易,但性能会受到影响,因为子选择将针对每个返回的行执行。

一个更好的方法,是更新的支撑功能,包括连接标准(IE:“where x.id = t.id”为缺乏真正的一)在SELECT:

SELECT x.id 
     x.column 
    FROM x1 x 

...所以你可以使用它作为JOIN:

SELECT t.id, ... 
     x1.column 
    FROM TABLE t 
    JOIN (SELECT x.id, 
       x.column 
      FROM MY_PACKAGE.x) x1 ON x1.id = t.id 

我更喜欢具有掺入功能逻辑进入查询进行维护的缘故,但有时不能得到帮助。

+0

+1,在这里工作有多个问题,我想到了这一点,但只是从SELECT中插入INSERT。你解释的功能问题比我更好... – 2009-09-25 14:15:06

+0

有人可以编辑以上评论我..我想添加代码段 – 2009-09-25 14:29:50

+0

编辑你的问题,并把代码放在那里,据我可以告诉你只能__BOLD__和_ITALICS_中的评论,没有代码格式 – 2009-09-25 14:34:57

1

就我个人而言,我会创建一个SSIS导入来完成这项任务。使用abulk插入您可以极大地提高速度,SSIS可以在批量插入后处理函数部分。