• 技术文章 >后端开发 >php教程

    (Oralce)Web翻页优化实例_PHP

    2016-06-01 12:40:48原创331
    Web翻页优化实例

    作者:Wanghai





    环境:

    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
    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:php5学习笔记(转)_PHP 下一篇:结合PHP使用HTML表单_PHP
    PHP编程就业班

    相关文章推荐

    • 28道PHP面试题,带你梳理基础知识!• php 购物车的例子_php实例• 哪位高手有ZF1.9最简单的入门程序• 求指导简化~解决办法• 小弟想学习php,哪位前辈可以给小弟介绍一下学习php很好的书或者学习视频,该怎么处理

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网