具有复合主键的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
你能修改一下变量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。