具有复合主键的SQL请求

本文关键字:SQL 请求 复合 | 更新日期: 2023-09-27 18:10:07

我必须从两个数据库中获取信息。一个是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相比,这个也很慢。

更多的数字:表1目前有大约。600 k行

我尝试了这些变体,得到了以下执行时间:
对于100个请求对象:
变体1:3900ms
变体2:218ms

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

对于500个请求对象:
变种1:12796ms
变体2:exception SQL0954C
变体3:7061ms

只看时间,我更喜欢变体2,但有例外的问题。

数据库不在我的控制之下,我只有SELECT权限。对于这个用例,您认为什么是最好的?还有其他我没发现的可能性吗?

问候,
pkoeppe

具有复合主键的SQL请求

你能修改一下变量2吗

  • 定义游标
  • 批量收集100行(例如)到pl/sql表
  • 处理
  • 获取下100行

示例见http://oracletoday.blogspot.com/2005/11/bulk-collect_15.html

我在Oracle和Informix中遇到了一个非常类似的问题。

SQL0954C可以通过调整系统配置来解决。你探索过那条路吗?

对于变量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.

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

要找出2还是3是最好的,你需要研究这些查询的执行计划。

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

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