具有复合主键的SQL请求

时间:2011-09-28 10:32:09

标签: c# sql oracle db2

我必须从两个数据库中获取信息。一个是ORACLE,另一个是DB2。在我的程序(C#)中,我从ORACLE数据库中获取了对象的基本信息。在第二步中,我想添加保存在DB2中的信息。 DB2中的表具有复合主键,我不确定哪种是最佳的请求方式,或者是否存在我目前看不到的替代方法。

例如:COLUMN1和COLUMN2是复合主键。

变式1:

 SELECT * 
   FROM (SELECT COLUMN1, COLUNN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
           FROM TABLE1) AS TEMP 
  WHERE ID='2011_123456' 
     OR ID='2011_987654'

这里我认为缺点是,对于表中的每一行,字符串连接都是构建的,并且执行速度相对较慢,因为主键列已编制索引而新键不是。

变式2:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
  FROM TABLE1 
 WHERE (COLUMN1='2011' AND COLUMN2='123456') 
    OR (COLUMN1='2011' AND COLUMN2='987654')

这个非常快,但是每当我得到一个异常SQL0954C时(应用程序堆中没有足够的存储空间来处理语句)。

变式3:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
  FROM TABLE1 
 WHERE COLUMN1 IN ('2011') 
   AND COLUMN2 IN ('123456','987654')

与变体2相比,这个也很慢。

更多数字:TABLE1目前约有。 600k行

我尝试了变体并获得了以下执行时间:
对于100个请求的对象:
变式1:3900ms
变式2:218ms

对于400个请求的对象:
变式1:10983ms
变体2:266ms

对于500个请求的对象:
变式1:12796ms
变体2:异常SQL0954C
变式3:7061ms

只看时间我更喜欢变体2,但异常存在问题。

数据库不受我的控制,我只有SELECT权限。您认为这个用例最好的是什么?还有其他我没有看到的可能吗?

的问候,
pkoeppe

4 个答案:

答案 0 :(得分:0)

你可以修改

的变体2吗?
  • 定义了一个游标
  • 批量收集100行(例如)到pl / sql表
  • 进行处理
  • 获取接下来的100行

例如,请参阅http://oracletoday.blogspot.com/2005/11/bulk-collect_15.html

我遇到的问题与Oracle和Informix非常相似。

答案 1 :(得分:0)

变体2和3都是理智的。 1是不理智的 由于1中的计算列ID不在任何索引中,因此DB将被强制执行至少完整的索引扫描。在2和3中,DB可以使用column1和column2上的索引来过滤结果。

要了解2或3是否最佳,您需要研究这些查询的执行计划。

关于索引的另一个注释。相关索引将比2和3之间的差异重要得多。即使您只有选择权限,如果没有这样的索引,也可以建议DBA(column1,column2)上的复合索引。

修改
WHERE COL IN (...)中有许多值时,另一种常见的方法是创建一个包含所有值的临时表(如果您有权限)并改为与该临时表连接。有时您还需要在临时表上创建索引以使其表现良好 在某些DBMS中,您可以使用表值参数而不是临时表,但我找不到类似于DB2的内容。

答案 2 :(得分:0)

可以通过调整系统配置来解决SQL0954C问题。你有没有探索过那条大道? Find out more

答案 3 :(得分:0)

对于变体3,请更改

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
FROM TABLE1 
WHERE COLUMN1 IN ('2011') 
AND COLUMN2 IN ('123456','987654')

要:

SELECT COLUMN1, COLUMN2, COLUMN3, ..., COLUMN1||'_'||COLUMN2 AS ID 
FROM TABLE1 
WHERE COLUMN1 ='2011' 
AND COLUMN2 IN ('123456','987654')

如果您只搜索COLUMN1的一个值,则没有理由使用IN。