关于一个SQL语句的优化
高手们,我有一个问题想请教大家,
帮我看看这个 SQL 语句应该怎么优化,现在数据库这个SQL 语句的使用频率很高,但是?
执行效果却不是很理想,以下是这个语句生成的报告,
请大家帮我分析分析::SELECT SYNID,TITLE,DOCSRC,DOCFLAG,TNAME
FROM (SELECT SYNID,TITLE,DOCSRC,DOCFLAG,
TNAME FROM LX_DOCS WHERE GROUPID is NULL
OR ISMAIN is NULL OR GROUPID='3391' OR
ISMAIN='1' ORDER BY PUBLISHDATE DESC) WHERE
* ROWNUM <= 20002000 rows selected.Elapsed: 00:02:39.78Execution Plan
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2000 | 1644K| 198K (1)|
| 1 | COUNT STOPKEY | | | | |
| 2 | VIEW | | 3590K| 2883M| 198K (1)|
| 3 | SORT ORDER BY STOPKEY| | 3590K| 287M| 198K (1)|
| 4 | TABLE ACCESS FULL | LX_DOCS | 3590K| 287M| 198K (1)|
------------------------------------------------------------------------Note
-----
- 'PLAN_TABLE' is old version
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
740366 consistent gets
731647 physical reads
0 redo size
136707 bytes sent via SQL*Net to client
1848 bytes received via SQL*Net from client
135 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
2000 rows processed
高手们,我有一个问题想请教大家,
帮我看看这个 SQL 语句应该怎么优化,现在数据库这个SQL 语句的使用频率很高,但是?
执行效果却不是很理想,以下是这个语句生成的报告,
请大家帮我分析分析::SELECT SYNID,TITLE,DOCSRC,DOCFLAG,TNAME
FROM (SELECT SYNID,TITLE,DOCSRC,DOCFLAG,
TNAME FROM LX_DOCS WHERE GROUPID is NULL
OR ISMAIN is NULL OR GROUPID='3391' OR
ISMAIN='1' ORDER BY PUBLISHDATE DESC) WHERE
* ROWNUM <= 20002000 rows selected.Elapsed: 00:02:39.78Execution Plan
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2000 | 1644K| 198K (1)|
| 1 | COUNT STOPKEY | | | | |
| 2 | VIEW | | 3590K| 2883M| 198K (1)|
| 3 | SORT ORDER BY STOPKEY| | 3590K| 287M| 198K (1)|
| 4 | TABLE ACCESS FULL | LX_DOCS | 3590K| 287M| 198K (1)|
------------------------------------------------------------------------Note
-----
- 'PLAN_TABLE' is old version
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
740366 consistent gets
731647 physical reads
0 redo size
136707 bytes sent via SQL*Net to client
1848 bytes received via SQL*Net from client
135 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
2000 rows processed
解决方案 »
- SQL语句里的值能不能暂时保存着,以便下面的值要用?
- [急切求助]如何在Linux环境下使用OCI接口连接ORACLE?
- oracle9i客户端访问11g错误日志,请高手看是什么原因?
- oracle中的进程地址具体是指什么呢
- oracle10g 有这个工具 logminer viewer 吗?
- 装了个orcle,问些很基本的问题。
- OCI程序里面怎么判断运行过程中的连接中断呢
- 依次求002~009,003~009,004~009,005~009,006~009,007~009,008~009 ,009~009...........中的最大值
- JSP连接ORACLE 9i数据库,出现"流已被关闭"的错误
- 我想给一个已定义的表中的一个字段定义为主建,sql语句该怎么写。
- 触发器和序列的问题
- 重分悬赏,大家进来看看.进都有分,而且问题很有趣味
/--order by PUBLISHDATE DESC,重要吗?如果不是,改一下:
SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM (SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM LX_DOCS
WHERE GROUPID is NULL
OR ISMAIN is NULL
OR GROUPID = '3391'
OR ISMAIN = '1')
WHERE * ROWNUM <= 2000;
/--还可以试一下:SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM (SELECT rownum rn,SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM LX_DOCS
WHERE GROUPID is NULL
OR ISMAIN is NULL
OR GROUPID = '3391'
OR ISMAIN = '1'
ORDER BY PUBLISHDATE DESC) tab
WHERE tab.rn <= 2000;
ISMAIN='1'
如果GROUPID和ISMAIN字段不是字符型的,是int型的话就不要查询字符串,去掉单引号查询,当然,如果是字符类型的就不能优化了
groupid 和 isman 这2个字段上有索引吗?
据字段函义分析,ismain 这个字段不需要建索引。
考虑到按publishdate排序,取大的2000条,所以在这个字段上建索引create index idx_lx_docs_x1 ON lx_docs(publishdate);--分析这个索引
dbms_stats.GATHER_INDEX_STATS(user, 'idx_lx_docs_x1');SELECT SYNID,TITLE,DOCSRC,DOCFLAG,TNAME
FROM (
SELECT /*+ index(idx_lx_docs_x1) */
SYNID,TITLE,DOCSRC,DOCFLAG, TNAME
FROM LX_DOCS
WHERE (GROUPID is NULL OR GROUPID='3391')
OR /*这个or 会不会是and? */
(ISMAIN is NULL OR ISMAIN='1')
ORDER BY PUBLISHDATE DESC
)
WHERE ROWNUM <= 2000
dbms_stats.GATHER_INDEX_STATS(trswcm, 'LX_DOCS_PUBLISHDATE');不能执行
dbms_stats.GATHER_INDEX_STATS(user, 'idx_lx_docs_x1');单独执行这一句,不需要改user的,要不就是:
dbms_stats.GATHER_INDEX_STATS('你的用户名', 'idx_lx_docs_x1');
create index idx_lx_docs_x1 ON lx_docs(publishdate)
*
ERROR at line 1:
ORA-00942: table or view does not exist
Elapsed: 00:00:00.08然后找到了已经存在的索引是: LX_DOCS_PUBLISHDATE ----- PUBLISHDATE
分析这个索引
dbms_stats.GATHER_INDEX_STATS('trswcm', 'LX_DOCS_PUBLISHDATE');
SQL> dbms_stats.GATHER_INDEX_STATS('trswcm', 'LX_DOCS_PUBLISHDATE');
SP2-0734: unknown command beginning "dbms_stats..." - rest of line ignored.
sql>exec dbms_stats.GATHER_INDEX_STATS('trswcm', 'LX_DOCS_PUBLISHDATE');
TNAME FROM LX_DOCS WHERE GROUPID is NULL
OR ISMAIN is NULL OR GROUPID='3391' OR
ISMAIN='1' and ROWNUM <= 2000
ORDER BY PUBLISHDATE DESC
然后执行4楼的:
SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM (SELECT rownum rn,SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM LX_DOCS
WHERE GROUPID is NULL
OR ISMAIN is NULL
OR GROUPID = '3391'
OR ISMAIN = '1'
ORDER BY PUBLISHDATE DESC) tab
WHERE tab.rn <= 2000;
看看是不是会快点?
CREATE INDEX i_test1 ON lx_docs(nvl(groupid,'x'),nvl(ismain,'x')); SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM (SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM LX_DOCS
WHERE GROUPID IN ('3391', 'x')
OR ISMAIN IN ('1', 'x')
ORDER BY PUBLISHDATE DESC)
WHERE ROWNUM <= 2000 ;
CREATE INDEX i_test1 ON lx_docs(nvl(groupid,'x'),nvl(ismain,'x'));
SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM (SELECT SYNID, TITLE, DOCSRC, DOCFLAG, TNAME
FROM LX_DOCS
WHERE nvl(GROUPID) IN ('3391', 'x')
OR nvl(ISMAIN) IN ('1', 'x')
ORDER BY PUBLISHDATE DESC)
WHERE ROWNUM <= 2000 ;