sql - 优化Oracle order by query

标签 sql oracle optimization query-optimization partitioning

我有一个大约 500 万行的表,如下所示:

Erp_in:

corr_id varchar(50) (almost Unique)
corr_type nvarchar(1) (4 distinct values)
interface varchar(20) (around 10 distinct values)
indate DateTime

有 3 个不同的索引(corr_id、interface 和 indate)
而且我还有另一个表,我通常将它与原始表连接起来,大约有 100000 行

Erp_In_failed:
corr_id
interface
error (clob)   
input (clob)

带有索引(corr_id 和接口(interface))

我要优化的查询很简单:
SELECT a.corr_id, a.interface, a.indate, b.error 
FROM erp_in a left join erp_in_failed b on a.corr_id = b.corr_id and a.interface =          b.interface
Order by a.indate desc;

如果我删除订单,查询不会花费那么长时间,但订购数据大约需要 3 分钟,如果不是更多的话。

我可以做些什么来优化查询?
我正在考虑分区/将旧数据删除到历史表/可能创建一个序列主键并按它或您想到的任何其他东西排序......

编辑:
执行计划说全表扫描,不是join需要这么长时间,而是order by。
即使这个查询也需要永远:
SELECT * FROM erp_in
ORDER BY indate;

我尝试过使用 Paging,但这也不起作用,并且需要几分钟才能获得 20 个结果,也许我做错了?

如果我在 indate 字段上添加 WHERE 子句,它会使用索引,但仅当它小于 20 天时,除此之外的任何内容仍使用全表扫描。 (即使有 40 天,添加 INDEX 提示使查询运行得更快,但仍然不够)。

只是为了好奇,我有一个包含 100 万行的简单表,order by 需要几秒钟,有什么区别? 100 万是否足以在 RAM 中对其进行排序?

谢谢,

最佳答案

您正在对 500 万行进行排序,其中包括大约 10 万个 clob。您不太可能在内存中做到这一点。如果您在带有统计信息的 SQL*Plus 中运行查询,您应该会看到查询大量写入磁盘。

提高性能的一种方法是向缓冲区缓存添加更多 GB,但这可能是一个昂贵的选择,也不是一个快速的选择。

erp_in(indate desc, corr_id, interface) 上构建复合索引也可以提供帮助,因为驱动表的结果将被预先排序,因此排序应该花费更少的工作。 INDATE 分区可能有类似的效果,但分区是企业版的额外收费,因此不是一个便宜的修复(获取更多内存可能会便宜很多)。

您对归档旧数据的引用表明您实际上并不想检索所有记录。如果是这种情况,那么使用 WHERE 子句减小结果集的大小会很有帮助。调整某些东西的最简单方法是首先不做工作。

添加主键并按其排序不会减少实际排序所需的工作量。

"so should I partition by date? will it help without adding WHERE clause on INDATE field"



这取决于。分区引入了表的一些物理组织,因此行将(至少)需要较少的排序。少多少取决于分区的粒度:按一天的范围进行分区,并且表几乎已经处于 INDATE 顺序,按一年的范围进行分区,而且情况要少得多。

但是,请记住,分区主要不是性能选项。它是管理数据(尤其是加载和可用性)的一个选项。事实上,它可能会降低某些查询的性能,这些查询不适合分区键应用的排序。

那么,你应该按日期分区吗?不是我们能回答的问题。回答它需要对您的系统有深入的了解,而我们却缺乏这种知识。但是,如果您拥有许可证,那么您当然应该进行调查和基准测试。

关于sql - 优化Oracle order by query,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13173709/

相关文章:

Mysql分组计数日期范围内的数据行

java - 在Java中将大约80000条大数据插入postgres数据库失败

regex - PL/SQL 优化在 varchar 中搜索日期

linux - 使用 oracle 以外的其他 linux 用户连接到 sqlplus

javascript - 用零初始化javascript数组

mysql - 复合或单一唯一索引约束?

sql - ORACLE SQL 如果另一个时间戳不在此范围内,则显示所有日期/时间范围

performance - Oracle SQL 占用巨大的临时空间

c++ - 模块化算法和 NTT(有限域 DFT)优化

c - 消除GOT寄存器的冗余负载?