Oracle SQL:选择非常大的表的子集的最佳方法是什么
我在这些论坛上漫游了几年,我总是发现我的问题已经被问到了,一个合适的答案已经出现了 虽然我现在有一个非常普通(也许很简单)的问题,但我还没有找到一个问同样问题的帖子 情况:Oracle SQL:选择非常大的表的子集的最佳方法是什么,sql,oracle,performance,Sql,Oracle,Performance,我在这些论坛上漫游了几年,我总是发现我的问题已经被问到了,一个合适的答案已经出现了 虽然我现在有一个非常普通(也许很简单)的问题,但我还没有找到一个问同样问题的帖子 情况: 我有一个付款表,每天有10-50万条记录,有10天的历史记录和数百列。大约有10-20列被索引。其中一个索引是批次id 我有一个批处理表,它的记录和列要少得多,比如说每天10k和30列 如果我想选择某个特定发件人的所有付款,我可以这样做: Select * from payments p where p.sender_
- 我有一个付款表,每天有10-50万条记录,有10天的历史记录和数百列。大约有10-20列被索引。其中一个索引是批次id
- 我有一个批处理表,它的记录和列要少得多,比如说每天10k和30列
Select * from payments p
where p.sender_id = 'SenderA'
这会运行一段时间,即使发送者id也被索引。因此我认为,最好先选择批次,然后使用批次id进入付款表:
select * from payments p
where p.batch_id in
(select b.batch_id from batches where b.sender_id = 'SenderA')
--and p.sender_id = 'SenderA'
现在,我的问题是:
- 在第二个脚本中,我是否应该在payments表的where子句中取消对Sender_id的注释?对发送者id进行两次筛选感觉不是很有效,即使它位于不同的表中李>
- 如果我将其设置为内部联接而不是嵌套查询,是否会更好
- 如果我将其设置为公共表表达式而不是嵌套查询或内部联接,会更好吗
在最坏的情况下,两个查询应该同时运行,在最好的情况下,我希望第一个查询运行得更快。如果运行较慢,则其他地方存在一些问题。在第二个查询中不需要附加条件 第一个查询将检索单个值的索引项,因此访问的块将少于第二个查询,第二个查询必须查找多个批次的索引项(以及执行子查询,但这可能并不重要) 但与Oracle一样的危险是,有很多因素决定优化器选择哪种查询计划。我将立即验证您的索引列的统计信息是否是最新的。如果不是,这可能是你的问题,你不需要进一步阅读 下一步是获取查询执行计划。我的猜测是,这将告诉您,您的查询正在运行一个完整的表扫描 Oracle是否选择对此类查询执行完整表扫描取决于返回的行数,以及Oracle是否认为使用索引或仅读取整个表更有效。在这两者之间切换的阈值不是一个固定的数字:它取决于许多因素,其中之一是名为
DB\u FILE\u MULTIBLOCK\u READ\u COUNT的参数
这是由Orale设置的,从理论上讲,它的配置应该确保索引查询和完整表扫描查询之间的转换应该是平滑的。换句话说,在转换点,当查询返回足够的行以提高整个表扫描的效率时,索引扫描和表扫描的时间应该大致相同
不幸的是,我看到过这样的系统,Oracle转而太快地进行全表扫描,一旦行数超过某个阈值,就会导致很长的查询时间
正如我之前所说,首先检查你的统计数据。如果这不起作用,请获得QEP并开始调优您的Oracle实例
调优Oracle是一个非常复杂的问题,这里无法完全回答,因此我不得不推荐链接。以下是有关参数的有用页面:减少它可能会有所帮助:
除此之外,通用Oracle性能调优指南如下:
如果你仍然有问题,你需要进一步调查,然后提出一个更具体的问题
编辑:
根据您的评论,您说您的查询返回了表中10M-50M的4M行。如果它是10米中的4米,那么索引就没有任何用处。即使50米中有4米,完全表扫描仍然是最有效的方法
您说您有很多列,所以这个4M行提取可能返回了大量数据
也许你可以考虑分解一些不需要的列,把它们放在子表中。特别是,如果有包含大量数据的列(例如,一些文本注释或其他内容),则最好将它们保留在主表之外
请记住-small很快,不仅在行数方面,而且在每行的大小方面。查询返回多少行?问题的简短回答:1)如果两列(批处理id和发送者id)都以相同的方式索引,那么第一个简单查询会更有效。2) 视情况而定。在大多数情况下,Oracle将创建相同的解释计划,因此这并不重要。3) 与第二个答案相同。可能提高性能的几件事:为此类查询保持表和索引统计信息的最新状态单列索引将是最有效的谢谢。返回的行通常是4M左右。这两个表是分区的吗?这会有很大帮助。。。此外,您可以尝试使用和构造来具体化两个子集(付款
或批次
为发送者id
)中的一个子集。。。无论如何,您必须比较执行计划以选择查询的形式。这个问题应该得到更广泛的回答,因为OP显然存在真正的性能问题。问题是:“什么是查询此问题的最佳方式?”答案是:1。SQL是一种声明性语言。这意味着,你可以指定你喜欢什么,而不是如何。谢谢,我认为这个答案解释了问题,并且