Web翻页优化实例

提交时间: 2004-6-18 15:37:49      回复    发消息

环境:

Linux version 2.4.20-8custom (root@web2) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #3 SMP Thu Jun 5 22:03:36 CST 2003

Mem:  2113466368

Swap: 4194881536

CPU:两个超线程的Intel(R) Xeon(TM) CPU 2.40GHz

优化前语句在mysql里面查询15秒左右出来,转移到oracle后进行在不调整索引和语句的情况下执行时间大概是4-5秒,调整后执行时间小于0.5秒。

翻页语句:

SELECT * FROM  (SELECT T1.*, rownum as linenum FROM  (

SELECT /*+ index(a ind_old)*/

a.category FROM auction_auctions a WHERE a.category =' 170101 ' AND a.closed='0' AND ends > sysdate AND (a.approve_status>=0)  ORDER BY a.ends) T1  WHERE rownum < 18681) WHERE linenum >= 18641

被查询的表:auction_auctions(产品表)

表结构:

SQL> desc auction_auctions;

Name                                      Null?    Type

----------------------------------------- -------- ----------------------------

ID                                        NOT NULL VARCHAR2(32)

USERNAME                                           VARCHAR2(32)

TITLE                                              CLOB

GMT_MODIFIED                              NOT NULL DATE

STARTS                                    NOT NULL DATE

DESCRIPTION                                        CLOB

PICT_URL                                           CLOB

CATEGORY                                  NOT NULL VARCHAR2(11)

MINIMUM_BID                                        NUMBER

RESERVE_PRICE                                      NUMBER

BUY_NOW                                            NUMBER

AUCTION_TYPE                                       CHAR(1)

DURATION                                           VARCHAR2(7)

INCREMENTNUM                              NOT NULL NUMBER

CITY                                               VARCHAR2(30)

PROV                                               VARCHAR2(20)

LOCATION                                           VARCHAR2(40)

LOCATION_ZIP                                       VARCHAR2(6)

SHIPPING                                           CHAR(1)

PAYMENT                                            CLOB

INTERNATIONAL                                      CHAR(1)

ENDS                                      NOT NULL DATE

CURRENT_BID                                        NUMBER

CLOSED                                             CHAR(2)

PHOTO_UPLOADED                                     CHAR(1)

QUANTITY                                           NUMBER(11)

STORY                                              CLOB

HAVE_INVOICE                              NOT NULL NUMBER(1)

HAVE_GUARANTEE                            NOT NULL NUMBER(1)

STUFF_STATUS                              NOT NULL NUMBER(1)

APPROVE_STATUS                            NOT NULL NUMBER(1)

OLD_STARTS                                NOT NULL DATE

ZOO                                                VARCHAR2(10)

PROMOTED_STATUS                           NOT NULL NUMBER(1)

REPOST_TYPE                                        CHAR(1)

REPOST_TIMES                              NOT NULL NUMBER(4)

SECURE_TRADE_AGREE                        NOT NULL NUMBER(1)

SECURE_TRADE_TRANSACTION_FEE                       VARCHAR2(16)

SECURE_TRADE_ORDINARY_POST_FEE                     NUMBER

SECURE_TRADE_FAST_POST_FEE                         NUMBER

表记录数及大小

SQL> select count(*) from auction_auctions;

COUNT(*)

----------

537351

SQL> select segment_name,bytes,blocks from user_segments where segment_name ='AUCTION_AUCTIONS';

SEGMENT_NAME          BYTES     BLOCKS

AUCTION_AUCTIONS      1059061760     129280

表上原有的索引

create index ind_old on auction_auctions(closed,approve_status,category,ends) tablespace tbsindex compress 2;

SQL> select segment_name,bytes,blocks from user_segments where segment_name = 'IND_OLD';

SEGMENT_NAME           BYTES     BLOCKS

IND_OLD                   20971520       2560

表和索引都已经分析过,我们来看一下sql执行的费用

SQL> set autotrace trace;

SQL> SELECT * FROM  (SELECT T1.*, rownum as linenum FROM  (SELECT a.* FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends  > sysdate AND (a.approve_status>=0)  ORDER BY a.ends) T1  WHERE rownum <18681) WHERE linenum >= 18641;

40 rows selected.

Execution Plan

----------------------------------------------------------

0      SELECT STATEMENT Optimizer=CHOOSE (Cost=19152 Card=18347 Byt

es=190698718)

1    0   VIEW (Cost=19152 Card=18347 Bytes=190698718)

2    1     COUNT (STOPKEY)

3    2       VIEW (Cost=19152 Card=18347 Bytes=190460207)

4    3         TABLE ACCESS (BY INDEX ROWID) OF 'AUCTION_AUCTIONS'

(Cost=19152 Card=18347 Bytes=20860539)

5    4           INDEX (RANGE SCAN) OF 'IND_OLD' (NON-UNIQUE) (Cost

=810 Card=186003)

Statistics

----------------------------------------------------------

0  recursive calls

0  db block gets

19437  consistent gets

18262  physical reads

0  redo size

114300  bytes sent via SQL*Net to client

56356  bytes received via SQL*Net from client

435  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

40  rows processed

我们可以看到这条sql语句通过索引范围扫描找到最里面的结果集,然后通过两个view操作最后得出数据。其中18502  consistent gets,17901  physical reads

我们来看一下这个索引建的到底合不合理,先看下各个查寻列的distinct值

select count(distinct ends) from auction_auctions;

COUNT(DISTINCTENDS)

-------------------

338965

SQL> select count(distinct category) from auction_auctions;

COUNT(DISTINCTCATEGORY)

-----------------------

1148

SQL> select count(distinct closed) from auction_auctions;

COUNT(DISTINCTCLOSED)

---------------------

2

SQL> select count(distinct approve_status) from auction_auctions;

COUNT(DISTINCTAPPROVE_STATUS)

-----------------------------

5

页索引里列平均存储长度

SQL> select avg(vsize(ends)) from auction_auctions;

AVG(VSIZE(ENDS))

----------------

7

SQL> select avg(vsize(closed)) from auction_auctions;

AVG(VSIZE(CLOSED))

------------------

2

SQL> select avg(vsize(category)) from auction_auctions;

AVG(VSIZE(CATEGORY))

--------------------

5.52313106

SQL> select avg(vsize(approve_status)) from auction_auctions;

AVG(VSIZE(APPROVE_STATUS))

--------------------------

1.67639401

我们来估算一下各种组合索引的大小,可以看到closed,approve_status,category都是相对较低集势的列(重复值较多),下面我们来大概计算下各种页索引需要的空间

column               distinct num        column len

ends                  338965              7

category               1148                5.5

closed                 2                   2

approve_status          5                   1.7

index1: (ends,closed,category,approve_status) compress 2

ends:distinct number---338965

closed: distinct number---2

index size=338965*2*(9+2)+ 537351*(1.7+5.5+6)=14603998

index2: (closed,category,ends,approve_status)

closed: distinct number---2

category: distinct number---1148

index size=2*1148*(2+5.5)+537351*(7+1.7+6)=7916279

index3: (closed,approve_status,category,ends)

closed: distinct number---2

approve_status: distinct number―5

index size=2*5*(2+1.7)+537351*(7+5.5+6)=9941030

结果出来了,index2: (closed,category,ends,approve_status)的索引最小

我们再来看一下语句

SELECT * FROM  (SELECT T1.*, rownum as linenum FROM  (SELECT a.* FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends  > sysdate AND (a.approve_status>=0)  ORDER BY a.ends) T1  WHERE rownum <18681) WHERE linenum >= 18641;

可以看出这个sql语句有很大优化余地,首先最里面的结果集SELECT a.* FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends  > sysdate AND (a.approve_status>=0)  ORDER BY a.ends,这里的话会走index range scan,然后table scan by rowid,这样的话如果符合条件的数据多的话相当耗资源,我们可以改写成

SELECT a.rowid FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends  > sysdate AND (a.approve_status>=0)  ORDER BY a.ends

这样的话最里面的结果集只需要index fast full scan就可以完成了,再改写一下得出以下语句

select * from auction_auctions where rowid in (SELECT rid FROM  (

SELECT T1.rowid rid, rownum as linenum FROM

(SELECT a.rowid FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends > sysdate AND

(a.approve_status>=0)  ORDER BY a.ends) T1  WHERE rownum < 18681) WHERE linenum >= 18641)

下面我们来测试一下这个索引的查询开销

select * from auction_auctions where rowid in (SELECT rid FROM  (

SELECT T1.rowid rid, rownum as linenum FROM

(SELECT a.rowid FROM auction_auctions a WHERE a.category like '18%' AND a.closed='0' AND ends > sysdate AND

(a.approve_status>=0)  ORDER BY a.closed,a.ends) T1  WHERE rownum < 18681) WHERE linenum >= 18641)

Execution Plan

----------------------------------------------------------

0      SELECT STATEMENT Optimizer=CHOOSE (Cost=18698 Card=18344 Byt

es=21224008)

1    0   NESTED LOOPS (Cost=18698 Card=18344 Bytes=21224008)

2    1     VIEW (Cost=264 Card=18344 Bytes=366880)

3    2       SORT (UNIQUE)

4    3         COUNT (STOPKEY)

5    4           VIEW (Cost=264 Card=18344 Bytes=128408)

6    5             SORT (ORDER BY STOPKEY) (Cost=264 Card=18344 Byt

es=440256)

7    6               INDEX (FAST FULL SCAN) OF 'IDX_AUCTION_BROWSE'

(NON-UNIQUE) (Cost=159 Card=18344 Bytes=440256)

8    1     TABLE ACCESS (BY USER ROWID) OF 'AUCTION_AUCTIONS' (Cost

=1 Card=1 Bytes=1137)

Statistics

----------------------------------------------------------

0  recursive calls

0  db block gets

2080  consistent gets

1516  physical reads

0  redo size

114840  bytes sent via SQL*Net to client

56779  bytes received via SQL*Net from client

438  SQL*Net roundtrips to/from client

2  sorts (memory)

0  sorts (disk)

40  rows processed

可以看到consistent gets从19437降到2080,physical reads从18262降到1516,查询时间也丛4秒左右下降到0。5秒,可以来说这次sql调整取得了预期的效果。

又修改了一下语句,

SQL> select * from auction_auctions where rowid in

2  (SELECT rid FROM  (

3  SELECT T1.rowid rid, rownum as linenum FROM

4  (SELECT a.rowid FROM auction_auctions a

5     WHERE a.category like '18%' AND a.closed='0' AND ends > sysdate AND

a.approve_status>=0

6    7  ORDER BY a.closed,a.category,a.ends) T1

8  WHERE rownum < 18600) WHERE linenum >= 18560)    ;

40 rows selected.

Execution Plan

----------------------------------------------------------

0      SELECT STATEMENT Optimizer=CHOOSE (Cost=17912 Card=17604 Byt

es=20367828)

1    0   NESTED LOOPS (Cost=17912 Card=17604 Bytes=20367828)

2    1     VIEW (Cost=221 Card=17604 Bytes=352080)

3    2       SORT (UNIQUE)

4    3         COUNT (STOPKEY)

5    4           VIEW (Cost=221 Card=17604 Bytes=123228)

6    5             INDEX (RANGE SCAN) OF 'IDX_AUCTION_BROWSE' (NON-

UNIQUE) (Cost=221 Card=17604 Bytes=422496)

7    1     TABLE ACCESS (BY USER ROWID) OF 'AUCTION_AUCTIONS' (Cost

=1 Card=1 Bytes=1137)

Statistics

----------------------------------------------------------

0  recursive calls

0  db block gets

550  consistent gets

14  physical reads

0  redo size

117106  bytes sent via SQL*Net to client

56497  bytes received via SQL*Net from client

436  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

40  rows processed

在order by里加上索引前导列,消除了

6    5             SORT (ORDER BY STOPKEY) (Cost=264 Card=18344 Byt

es=440256)

,把consistent gets从2080降到550

oracle优化查询前几条,一个查询优化的分析调整全过程!很值得一看相关推荐

  1. oracle分页查询前10条,Oracle查询前十条记录及分页查询(第5条到第10记录)

    Oracle查询前10条记录及分页查询(第5条到第10记录) 如果你想了解Oracle查询前10条记录的相关实际应用方案的话,你就可以点击以下的文章对其在实际相关操作中的正确用法,有一个更加完善的认识 ...

  2. 增大max_result_window是错的,ES只能查询前10000条数据的正确解决方案

    文章目录 1.问题现象描述 2.错误的解决方案 2.1 使用`max_result_window`的错误解决方案 2.2 官方对`max_result_window`参数的解释 2.3 官方推荐的解决 ...

  3. SQL查询前10条记录(SqlServer/mysql/oracle)[语法分析]

    Sql Server : Sql代码 select top X * from table_name --查询前X条记录,可以改成需要的数字. select top n * from (select t ...

  4. oracle以10个记录为一页查询,SQL查询前10条记录(SqlServermysqloracle)语法分析

    SQL查询前10条记录(SqlServer/mysql/oracle)语法分析 Sql Server : Sql代码 select top X * from table_name --查询前X条记录, ...

  5. 不同数据库中查询前几条记录的用法(SQL Server/Oracle/Postgresql)

    SQL在不同数据库中查询前几条记录的用法分类 1. orACLE Select * FROM TABLE1 Where ROWNUM<=N 2. INFORMIX Select FIRST N ...

  6. 各种数据库查询前几条数据的方法

    sql在不同数据库查询前几条数据 关键字: sql 前几条结果  sql在不同数据库查询前几条数据  1. ORACLE    SELECT * FROM TABLE1 WHERE ROWNUM< ...

  7. sql查询前10条、第11条到第15条数据

    SQL查询10条数据 查询前10条数据 查询第11条到第15条数据 查询前10条数据 MySQL.PostgreSQL使用limit select * from 表名 order by id(主键)l ...

  8. 查询前几条记录SQL在不同数据库中的用法

    13,(1)查询前几条记录SQL在不同数据库中的用法; 1. ORACLE SELECT * FROM TABLE1 WHERE ROWNUM<=N 2. INFORMIX SELECT FIR ...

  9. sql查询前50条_您必须知道的前50条SQL查询

    sql查询前50条 In this article, we'll go over the most common SQL queries that you should know to be able ...

最新文章

  1. 记一次金士顿DT100 G3 32G修复
  2. yota3墨水屏设置_国产墨水屏“手写平板”评测,10.3英寸大屏,支持无纸化办公...
  3. redis watch使用场景_[Redis] 常用类型及应用场景
  4. 【Redis系列】深入浅出Redis主从复制之读写分离【一篇搞懂Redis复制】
  5. 程序员如何高效的学习?
  6. STM32F407 CubeMx使用定时器测量信号频率 分辨率0.001Hz
  7. 编写程序,定义一个方法,能够判断一个1~9999之间的数是否是回文数。
  8. logagent同步mysql_LogAgent的工作流程
  9. 上了高中应该注意什么?
  10. 仅需6道题轻松掌握Python异常捕获 | Python技能树征题
  11. 卷影副本(Shadow Copies)
  12. 四川大学软件学院操作系统笔记
  13. 蓝牙精确定位技术下的化工厂安全管理系统,蓝牙定位标签-新导智能
  14. 国务院通过大数据发展行动纲要
  15. STM32F205 STM32F207 STM32F215 STM332F217 用户手册,使用手册,编程手册三合一下载地址
  16. MapReduce 基础案例 之 平均值 计算
  17. 完全卸载Office 2016 for Mac教程
  18. 3904三极管是什么功能_新方法讲解三极管工作原理
  19. 机器人学-笔记-斯坦福大学公开课-class 1
  20. 分享第三方支付申请流程政策

热门文章

  1. 笔记1:使用奇数卷积核的原因
  2. pycharm-实用教程和每日练习
  3. java里面的pai_Java - ZhangPai - 博客园
  4. oracle+快速客户端安装方法,ORACLE简易客户端安装与使用方法
  5. Linux 根据服务名字找安装路径
  6. 微信小程序中识别html标签的方法
  7. ajax post常用请求头
  8. python系列教程_python基础学习系列教程2-进阶之路中绕不开的知识点。
  9. Java 质数输出的经典算法题面试可以用
  10. JavaEE系统架构师学习路线