Oracle排序优化问题,求解决方案

秋雨飘落 2012-10-31 05:37:29
1.一张表内有3亿条数据,该表建立全文索引;

2.现在我以“张三”关键词去检索该表,我只需要前300条数据(rownum<=300),这样Oracle查够300条就不再

往下扫描,速度很快。SQL语句:select * from 表名 contains(text,'张三')>0 where rownum<=300;

3.但实际上张三这个关键词有10000条数据,如果我想先按时间排序(倒序)再取前300条,速度就很慢了,因

为如果有排序操作,Oracle会10000条结果集都检索出后再排序,然后才去取前300条,成本太高了,
SQL语句:select * from (select * from 表名 where contains(text,'张三')>0 order by 生产时间 desc)

where rownum<=300;

4.求解决方案提高检索速度。目的是:检索结果取前300条,但要求记录的生产时间最早的排前面。

5.一定给分。
...全文
758 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
土匪八号 2012-12-25
  • 打赏
  • 举报
回复
直接读取物理内存 select * from (select rid from (select a.rid, rownum rn from (select rowid rid from 表名 tr order by tr.d_createdate desc nulls last ) a) b) v1, 表名 tr where v1.rid = tr.rowid
leio 2012-12-21
  • 打赏
  • 举报
回复
select * from ( select /*+ FIRST_ROWS(300) */ a.* from 表名 a where contains(text,'张三') > 0 order by 生产时间 desc ) where rownum<=300 不知道这样行不行?
izj 2012-12-07
  • 打赏
  • 举报
回复
学习。。。。
BenChiM888 2012-12-06
  • 打赏
  • 举报
回复
人间正道是沧桑,这个是首选。 1、先查询结果,放入临时表,速度搜一下 2、10000条数据进行排序,速度搜一下 一步变成两步走,速度搜一下。 或者 还个一体机吧,曾几何时,一个在普通服务器上跑2三个小时都跑不出来的sql 在一体机上 搜一下 几秒就完事儿了。
引用 4 楼 zftang 的回复:
引用 1 楼 的回复:既然不排序,速度很快就出来了 那么:你可以先按条件查询出结果,并将其结果打入一个临时表,再在临时表中排序、取数据呗! 这样照样不可避免把张三的10000条记录也查出来了,再排序。
linwaterbin 2012-12-05
  • 打赏
  • 举报
回复
也可考虑使用临时表空间组--TTG
yurui05 2012-12-05
  • 打赏
  • 举报
回复
1 分区表之类的 你应该也考虑到了。可能业务原因不能使用分区表。 2 单独从sql语句上讲,只能这样查询。无更好的办法。 3 能否采用变通的方法? 假设你的业务是只需要前300条记录。在半夜某时间点调用job,将大表的前300条张三放入另一张表a中。而平时的查询是从另一张表中提取数据。
TargetOCM 2012-11-23
  • 打赏
  • 举报
回复
首先观察一下 张三这个人是否属于某个类别或者范围,如果是的话就用类别字段或者范围字段对表进行分区表处理 这样绝对可以提高查询速度! 假如你的表结构是这样 customers(id,name,dept) 你可以先建一个分区表 customers_t 语句如下: CREATE TABLE customers_t( id INT PRIMARY KEY , name VARCHAR (20), dept VARCHAR (10) ) PARTITION BY LIST (dept) ( PARTITION dept1 VALUES ('dept2') TABLESPACE xxx, PARTITION dept2 VALUES ('dept2') TABLESPACE xxx ); 然后执行 insert into customers_t select * from customers; rename customers to customers_old; rename customers_t to customers; 查询的时候这样写语句 select * from customers PARTITION (dept1); 上面所有语句用到的dept1 dept2 是dept字段的具体值,注意分区名后面的dept1不用加单引号,分区名规定必须字母开头且不能包含-
wohenkeai 2012-11-22
  • 打赏
  • 举报
回复
可以按照时间创建索引,这样每次产生数据的时候会自动按照顺序给你排好,这样每次查询的时候就不会排序了。
yehaver 2012-11-01
  • 打赏
  • 举报
回复
建议对此表进行时间分区管理,按照生产时间分区管理会快一点

partition by time(生产时间)
(
partition part01 values less than (to_data('2011-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) tablespace01,
partition part02 values less than (to_data('2012-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) tablespace02
)

毕竟你的数据上亿了,多了都会很慢的
fw0124 2012-11-01
  • 打赏
  • 举报
回复
你把查询计划发出来看看,
如果已经是带stopkey的sort(SORT ORDER BY STOPKEY),基本上就很难再优化了。
秋雨飘落 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
SQL code
-- 或者这样试试:
with a1 as (select ... from tb_name where name='张三'),
a2 as (select ... from a1 order by date_time desc)
select * from a2 where rownum<=300;
[/Quote]

还是不行的,解释计划中的IO消耗还是很高。
秋雨飘落 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
既然不排序,速度很快就出来了
那么:你可以先按条件查询出结果,并将其结果打入一个临时表,再在临时表中排序、取数据呗!
[/Quote]
这样照样不可避免把张三的10000条记录也查出来了,再排序。
luoyoumou 2012-10-31
  • 打赏
  • 举报
回复
-- 或者这样试试:
with a1 as (select ... from tb_name where name='张三'),
a2 as (select ... from a1 order by date_time desc)
select * from a2 where rownum<=300;
luoyoumou 2012-10-31
  • 打赏
  • 举报
回复
既然不排序,速度很快就出来了
那么:你可以先按条件查询出结果,并将其结果打入一个临时表,再在临时表中排序、取数据呗!

3,494

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧