Oracle 在执行动态生成的 SQL 查询时进行扩展

Posted

技术标签:

【中文标题】Oracle 在执行动态生成的 SQL 查询时进行扩展【英文标题】:Oracle scaling while executing dynamically generated SQL queries 【发布时间】:2014-03-13 07:54:56 【问题描述】:

我有一个用例,其中在用户中输入一些数据,然后在后端根据输入生成 SQL 查询。

用户输入多个过滤条件,这些条件会被翻译成新的 子句。例如(someCol1='valA' and someColB ='valP' )

用户可以输入多达 10000 个子句,数据库就会受到打击。

例如

select * from table where  (
(someCol1='valA' and someColB ='valP' ) OR
(someCol1='valB' and someColB ='valQ' ) OR
(someCol1='valC' and someColB ='valR' ) OR
(someCol1='valD' and someColB ='valS' ) OR
....
(someCol1='valE' and someColB ='valT' ) OR
)

问题是当子句数量很大(大约 1000 个)时,执行时间会增加。响应时间可能长达 5 分钟,但作业永远不会失败。

我使用的是 Oracle 数据库,但没有数据库连接。所有查询都针对单个数据库运行。

【问题讨论】:

您的问题缺少一些重要的细节。什么是 UI 应用程序?您是否可以控制 SQL 的生成方式?最重要的是:您担心什么?您是否对针对数据库运行查询时的性能问题或查询文本超过最大语句长度限制感到怀疑? 没有帮助,但这是一个糟糕的设计:让用户生成大量的 OR 查询。 @YaroslavShabalin 有某种二维表,根据用户选择的单元格生成一个子句。现在如果用户选择 N 个单元格,则将生成 N 个子句。缩放中的问题。如果用户选择 1000 个单元格,查询会运行很长时间,有时会失败 被查询的表有多大?如果有 10k or 子句,会返回多少? (听起来是个可怕的问题,抱歉。) 您可以尝试在(someCol1, someColB') or even one bitmap index on someCol1` 和someColB 上创建一个位图索引。 但是:位图索引在您对表执行大量 DML 的环境中效果不佳。如果索引有帮助,您将需要决定是否可以忍受这些缺点。顺便说一句:您不是加入“数据库”,而是加入 tables。在您的查询中只有一个 table,而不是一个“DB”。 【参考方案1】:

我可以推荐使用带有过滤器的临时表。

如果您有少量过滤器(SomeCol1、SomeColB、..),那么过滤器可以存储在“平面”表中:

FLTRS_TMP ( filter_seq_id, SomeCol1_id, SomeColB_id, ... )

然后您可以在特定列上加入表格:

select * from FACT_TABLE F, FLTRS_TMP FT
 where nvl(F.SomeCol1_id,'!null!') = nvl(FT.SomeCol1_id,'!null!')
   and nvl(F.SomeColB_id,'!null!') = nvl(FT.SomeColB_id,'!null!')
   and ...

但如果过滤器数量比较多,可以考虑将过滤器放在类属性(未透视)表中:

FLTRS_TMP ( filter_seq_id, filter_family_seq_id, column_name, column_value )

filter_family_seq_id 用于对AND 条件进行分组(分隔不同的OR 条件)。如果要使用不同的运算符您可以添加operator_id 列。最后 FLTRS_TMP 表最有可能在与 FACT_TABLE 连接之前进行透视。

【讨论】:

以上是关于Oracle 在执行动态生成的 SQL 查询时进行扩展的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle 动态 SQL 之后如何继续

执行Sql语句,包括存储过程,可以动态生成返回实体

mysql视图,存储过程,函数,事务,触发器,以及动态执行sql

oracle静态sql和动态sql

如何在 sqlplus 中调试 Oracle 动态 sql?

oracle里怎么对sql查询的日志进行查看