0
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 万条数据,执行这个查询需要 18 秒,在这个查询执行之前我们应该计算总计数大约需要 7 秒,所以它花费了 25 秒以上,有什么优化的想法吗?

4

1 回答 1

1

分页通常是一种向人类显示结果的机制。没有人愿意读取 200 万行数据。

因此,如果此查询确实将行呈现给真实的人,那么您需要解决的是将整个结果的大小减小到人类大小的大小。所以你需要在数据库中应用额外的过滤器并返回一个聚焦的结果集。不仅您的用户会感谢您,您的网络管理员也会感谢您。

另一方面,如果这种数据洪流的预期接收者是计算机或其他机械设备,那么就给它整个东西。机器大多不关心页面,或者如果他们关心页面(电子表格、打印机等),它们有内置的子例程来为我们处理分页。


所以这给我们留下了一个问题,即您的原始查询需要很长时间才能执行。如果没有任何解释计划或统计信息(有多少行table1符合搜索条件?这些值的限制程度如何kindid?)很难解决这个问题。

“kindid 是一种只有三个选择(0,1,3)的类型”

福特。如果 KINDID 只能有三个选择,那么在 WHERE 子句中使用它有什么意义?

事实上,从 WHERE 子句中删除它可能会显着提高查询的性能。除非您为该列收集了直方图,否则 Oracle 会假设这in (0,1,3)会以某种方式限制结果集;而只有当大多数行在该列中有 NULL 时,这才是正确的。如果是这种情况,最好使用kindid is not null.

于 2012-10-14T11:35:33.593 回答