如果您获取所有行,我的视图会非常慢。但是如果我选择一个子集(在where子句中提供ID),性能非常好。我无法对ID进行硬编码,因此我创建了一个子选择来从另一个表中获取ID。子选择仅返回一个ID。现在性能非常慢,似乎Oracle在使用where子句之前正在评估整个视图。我可以以某种方式帮助Oracle,以便SQL 2和3具有相同的性能吗?我正在使用Oracle 10g
1慢
从ci.my_slow_view
中选择*2快
从ci.my_slow_view中选择*,其中id = 1;
3慢
从ci.my_slow_view中选择*,其中id为(从active_ids中选择id)
答案 0 :(得分:2)
这是预期的行为...... 3很慢,因为Oracle将执行“全表扫描”,这意味着你的索引没有帮助(你的where子句不包含任何常量或范围,并且是无界的,这意味着无论你使用什么索引,所有的行都是可能是加入条件的候选人。
可能的改进: 首先,检查join / pk列上的索引是否正常(my_slow_view和active_ids中的id)。这是第二步所必需的: 其次,为您的表和视图生成表统计信息,这将使Oracle高速缓存内存优化器启动。 (它应该可以工作,因为假设你的active_ids表足够小,可以完全在内存中。)
第二种方法: 在PL / SQL中编写存储过程,其中id是in参数,并重写SQL,以便使用绑定参数。
这应该为您提供所需的灵活性(没有硬编码ID),以及最快查询的速度。
答案 1 :(得分:2)
怎么样
select * from ci.my_slow_view where id = (select id from active_ids)
将“in”替换为“=”将告诉Oracle您希望“select id from active_ids”只返回一行。
答案 2 :(得分:0)
我无法对ID进行硬编码,因此我创建了一个 sub select从另一个获取ID 表。子选择仅返回一个 ID。
最有可能的是,收集小表上的统计信息(虽然它包含一行)会有所帮助,因为这样可以帮助Oracle意识到它很小并鼓励它使用ID上的索引。
然而,听起来这确实不是解决原始问题的正确方法。通常,当想要使用不同的查找值重复执行查询时,最好的方法是使用绑定变量。在SQLPlus中执行此操作的基本方法是:
SQL> variable id number
SQL> exec :id := 1;
SQL> select * from ci.my_slow_view where id = :id ;
SQL> exec :id := 2;
SQL> select * from ci.my_slow_view where id = :id ;
实现这一点的细节取决于您正在开发的环境。
答案 3 :(得分:0)
或者:
select * from ci.my_slow_view, active_ids
where my_slow_view.id = active_ids.id;