Ami*_*mir 5 sql oracle optimization partitioning query-optimization
我有一个大约有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
Run Code Online (Sandbox Code Playgroud)
使用3个不同的索引(corr_id,interface和indate)
而且我还有另一个表,我通常会将其与原始表连接,大约有100000行
Erp_In_failed:
corr_id
interface
error (clob)
input (clob)
Run Code Online (Sandbox Code Playgroud)
带索引(corr_id和接口)
我想要优化的查询是简单的,因为:
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;
Run Code Online (Sandbox Code Playgroud)
如果我删除了订单,则查询不会花费那么长时间,但是如果不是更多,则对数据进行排序大约需要3分钟.
我该怎么做才能优化查询?我正在考虑将旧数据分区/删除到历史表/可能创建一个序列主键并按顺序或其他任何你想要的顺序...
编辑:
执行计划表示全表扫描,并且它不是连接需要这么长时间的顺序.
即使这个查询也需要永远:
SELECT * FROM erp_in
ORDER BY indate;
Run Code Online (Sandbox Code Playgroud)
我尝试过使用Paging,但这也不起作用,并且需要花费几分钟才能获得20个结果,也许我做错了?
如果我在indate字段上添加WHERE子句,它会使用索引,但只有当它小于20天时,除此之外的任何内容仍然使用全表扫描.(即使有40天,添加INDEX提示使查询运行得更快,但仍然不够).
只是为了好奇,我有一个简单的表,有100万行,订单需要几秒钟,有什么区别?是100万足以在RAM中排序?
谢谢,
您正在对 500 万行进行排序,其中包括大约十万个 Clob。你不太可能在记忆中做到这一点;如果您在 SQL*Plus 中运行带有统计信息的查询,您应该会看到查询大量写入磁盘。
提高性能的一种方法是向缓冲区高速缓存添加更多 GB,但这可能是一种昂贵的选择,而且也不是一个快速的选择。
构建复合索引erp_in(indate desc, corr_id, interface)也可能有所帮助,因为驱动表的结果将被预先排序,因此排序应该花费更少的工作。按 INDATE 进行分区可能会产生类似的效果,但分区对于企业版来说是额外收费的,因此并不是一个便宜的解决方案(使用更多内存可能会便宜很多)。
您提到归档旧数据表明您实际上并不希望检索所有记录。如果是这种情况,那么使用 WHERE 子句减小结果集的大小会有很大帮助。调整某些东西的最简单方法就是从一开始就不要做任何工作。
添加主键并按其排序不会减少实际排序所需的工作量。
“那么我应该按日期分区吗?如果不在 INDATE 字段上添加 WHERE 子句会有帮助吗”
这取决于。分区引入了表的一些物理组织,因此行(至少)需要较少的排序。减少多少取决于分区的粒度:按一天的范围进行分区,表几乎已经处于 INDATE 顺序,按一年的范围进行分区,情况要小得多。
但是,请记住,分区主要不是性能选项。它是管理数据(尤其是加载和可用性)的选项。事实上,它可能会降低某些查询的性能,这些查询不适合分区键应用的排序。
那么,您应该按日期分区吗?这不是我们可以回答的问题。回答这个问题需要对您的系统有深入的了解,而您拥有而我们缺乏。但如果您拥有许可证,那么您当然应该研究并进行基准测试。