繁体   English   中英

增强大型慢速数据加载查询的性能

[英]Enhance performance of large slow dataloading query

我正在尝试将数据从oracle加载到sql server(很抱歉,以前没有写过此信息)

我有一个表(实际上是一个视图,其中包含来自不同表的数据)至少具有一百万条记录。 我以一种具有业务逻辑功能的方式设计了程序包,并直接在select查询中调用它们。

例如:

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列,我至少要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;

我正在获取每一行并在C#中执行逻辑,然后插入

如果可能,请从SELECT中插入:

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

这将运行多单查询显著更快哪里,那么你在结果集循环,并为每个行的一个INSERT。

编辑作为OP问题编辑:

您应该能够在查询中替换对普通SQL的函数调用。 使用LEFT JOIN tableP模仿“ initial”,并且可以使用CASE计算“ RL”或“ GL”。

根据OP最近的评论进行编辑

由于您是将数据从Oracle加载到SQL Server中,所以我会这样做:大多数可以帮助您的人已经继续前进,不会再阅读此问题,因此在您说一个新问题的地方打开一个新问题:1)您需要加载数据(从Oracle(版本)到SQL Server版本2)当前,您正在通过一个查询来加载它,并处理C#中的每一行并将其插入SQL Server,这很慢。 以及所有其他详细信息。 有很多更好的方法将数据批量加载到SQL Server。 对于这个问题,您可以接受答案,在解释您需要提出新问题的地方回答自己,或者不接受。

我的建议是不要使用函数,然后在其他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

像在使用C#/ etc一样,封装在SQL中不起作用。 尽管该方法使维护更加容易,但是由于子选择将针对返回的每一行执行,因此性能会受到影响。

更好的方法是将支持功能更新为在SELECT中包括where x.id = t.id条件(即:缺少真实值的“ where x.id = t.id ”):

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

我更喜欢为了维护而不得不将函数逻辑合并到查询中,但是有时它无济于事。

我个人将创建一个SSIS导入来执行此任务。 使用大容量插件可以显着提高速度,而SSIS可以在批量插入后处理功能部件。

在表上创建一个排序的intex。

SQL Server Indizes简介 ,其他RDBMS相似。

编辑,因为您编辑了问题:

使用视图更为不理想,尤其是在从视图查询单行时。 我认为您的“业务功能”实际上类似于存储过程吗?

就像其他人建议的那样,在SQL中总是基于集合。 我以为您已经做到了,因此开始使用索引的提示。

一些提示:

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

首先,您需要找到实际的性能问题所在。 然后,您可以查看尝试解决它的方法。

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

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

    \n 创建表the_view_table\n \n 选择 *\n 从the_view;\n
  2. 功能执行得如何? 根据描述,您将进行大约500万个函数调用。 他们最好效率很高! 也定义为deterministic的功能。 如果使用deterministic关键字定义函数,则Oracle有机会优化一些调用。

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

      选择 \n   f.dim_id, \n   d.dim_col_1, \n   long_slow_function(d.dim_col_2)as dim_col_2\n 来自large_fact_table f\n 加入small_dim_table d on(f.dim_id = d.dim_id) 
      选择 \n   f.dim_id, \n   d.dim_col_1, \n   d.dim_col_2\n 来自large_fact_table f\n 加入(\n   选择 \n     dim_id, \n     dim_col_1, \n     long_slow_function(d.dim_col_2)as dim_col_2\n 来自small_dim_table)d on(f.dim_id = d.dim_id) 

    理想情况下,第二个查询应运行得更快,因为它调用函数的次数更少。

性能问题可能出在任何这些地方,并且在您调查问题之前,很难知道将调整工作定向到何处。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM