Sql 查询优化(解析函数)

Sql 查询优化(解析函数),sql,oracle,query-optimization,Sql,Oracle,Query Optimization,我有一张大桌子。 在这个表中,我们有产品和销售日期。 我想找出每种产品最近5次的销售情况。 很容易找到查询,但我想找到一个快速的? 例如: with foo as (select RANK() OVER(PARTITION BY product ORDER BY sale_date DESC) RK, p.* from sell p) select * from foo where rk < 6 但是这个查询会对每一行进行完整的表扫描和排序。 所以这不是一个有效的查询

我有一张大桌子。 在这个表中,我们有产品和销售日期。 我想找出每种产品最近5次的销售情况。 很容易找到查询,但我想找到一个快速的? 例如:

    with foo as
 (select RANK() OVER(PARTITION BY product ORDER BY sale_date DESC) RK, p.*
    from sell p)
select * from foo where rk < 6
但是这个查询会对每一行进行完整的表扫描和排序。 所以这不是一个有效的查询

有没有更好的办法

非常感谢

此查询:

with foo as (
      select RANK() OVER (PARTITION BY product ORDER BY sale_date DESC) as RK,
             p.*
      from sell p
     )
select *
from foo
where rk < 6;

可以利用有关sellproduct、sale_date的索引。

您必须在某个点扫描整个表,以满足功能要求:

我想找出每种产品最近5次的销售情况

你找不到比使用RANK之类的窗口函数更有效的方法了。不过严格地说,我会使用ROW_NUMBER来满足这一要求,因为RANK或DENSE_RANK可以重复值,所以你可能在一个产品上获得5行以上的数据

如果可以按日期限制子查询的范围,例如忽略6个月以上的所有销售,则可以避免表扫描。但根据你对需求的描述,这似乎并不适用。请注意,如果查询优化器认为您需要表的很大一部分而不值得使用索引,那么它可能会选择表扫描

select foo.*
FROM (
      select 
         ROW_NUMBER() OVER (PARTITION BY s.product ORDER BY s.sale_date DESC) as RN
       , s.*
      from sell s
     ) foo
where foo.rn < 6;

我避免使用化妆品CTEs CTE作为派生表子查询的替代品。

您看过该查询的解释计划了吗?你们有关于产品/销售日期的索引吗?但是,考虑到子查询中没有where子句,它可能总是进行完整扫描,并且也无法避免排序。我能看到的唯一选择是根据您的要求使用密集排列或行数。排名可以跳过数字。row_number将为每个产品提供不超过5行的内容。等级或密集等级可能会给你5以上。嗨,谢谢你的回答。是的,我有一个关于产品/销售日期的索引。我可以创建任何索引。但你说得对,这不是索引的问题。通过此查询,您可以对表或索引进行完整扫描。关键是在5行之后停止搜索。你认为有可能用行数或密集秩来实现吗?我很快就会试试的。拿一副牌来。去掉一些,忽略那些。剩下的人洗牌,面朝下摊在桌子上。现在选择5。它们是牌组中排名最靠前的牌吗?你现在必须做什么才能弄清楚这5张牌的排名?让我知道你进展如何。好的,我有一千种产品和千亿的销售额。因此,我相信,就五千行而言,有一个合适的查询或方法谢谢你的回答。我们已经有了这个索引。但是甲骨文做了一个快速的全扫描和排序。因此,我确信有更好的查询来查找行。可能带有滞后或行号以及windows范围。但是我不知道怎么做嗨,再次感谢你的帮助。我尝试了你的查询,但是计划、成本和持续时间与我的完全相同。所以它不起作用。直觉上,如果我们有一个索引要排序,可以说取前五行并停止,不是吗?另一件事,对不起,英语不是我的母语,那么CTE的意思是什么?常见的表表达式;以富为。。。