select * from (
select t_tmp_a.*, rownum t_tmp_id from (
select t.*, i.counts
from table1 t, (select id, count(id) counts from table2 group by id) i
where t.id=i.id and t.kindid in (0,1,3) order by t.id desc
) t_tmp_a where rownum <= 20) t_tmp_b where t_tmp_id >= 11;
table1和table2每个表有超过200万个数据,当执行此查询需要18s时,在执行此查询之前我们应该计算总计数需要大约7s,所以它花费超过25s,任何想法都要优化吗?
答案 0 :(得分:1)
分页通常是一种向人类展示结果的机制。没有人想要阅读200万行数据。
因此,如果此查询确实向真人展示行,那么您需要解决的问题是将整个结果的大小减小到人类大小。因此,您需要在数据库中应用其他过滤器并返回聚焦结果集。您的用户不仅会感谢您,网络管理员也是如此。
另一方面,如果这个数据泛滥的预期接收者是计算机或其他机械设备,那么就把它全部给它。机器大多不关心页面,或者如果它们(电子表格,打印机等),他们有内置的子程序来处理我们的分页。
这样我们就会遇到原始查询需要很长时间才能执行的问题。没有任何解释计划或统计数据(table1
中有多少行符合搜索条件?kindid
的那些值有多限制?)很难解决这个问题。
“kindid是一种只有三个选择(0,1,3)”
的类型
Fnord。如果KINDID只能有三个选项,那么在WHERE子句中使用它有什么意义呢?
实际上,将其从WHERE子句中删除可能会显着提高查询的性能。除非您收集了该列的直方图,否则Oracle会假设in (0,1,3)
以某种方式限制结果集;如果大多数行在该列中都为NULL,那么这只会是真的。如果是这种情况,最好使用kindid is not null
。