查看: 49970|回复: 86

[精华] 我的SQL调优公式T=S/V

[复制链接]
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
跳转到指定楼层
1#
发表于 2008-1-23 13:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
比较愚钝,从事调优工作这么些年,处理过的性能问题也不少,也就总结出这么个公式来

S指sql所需访问的资源总量,V指sql单位时间所能访问的资源量,T自然就是SQL执行所需时间了

这个公式很简单,调优的目标是减少T,T=S/V,那么我们要调的对象自然就要放到这里的S和V上,调优的方法就是围绕减少S和增大V

增大V(单位时间所能访问的资源量),在硬件设备不变的情况下所能做的只有充分利用现有资源,如:通过调整SGA充分利用物理MEMORY,通过并行处理充分利用CPU,通过调整IO分布充分利用硬盘处理能力,还有。。。。升级设备?

减少S(sql所需访问的资源总量),这通常是调优工作的重中之重,SQL调优的主要目的就是围绕着如何减少S在进行,在ORACLE中,所需访问的资源以block记,一条SQL执行所读写的block数直接影响到SQL的执行时间,如何知道SQL执行所读写的block数呢,简单的方法如下:
set autotrace traceonly
SQL> select count(*) from test;

已用时间:  00: 00: 10.01

执行计划
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 | 19342   (1)| 00:03:53 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST |  5285K| 19342   (1)| 00:03:53 |
-------------------------------------------------------------------


统计信息
----------------------------------------------------------
        204  recursive calls
          0  db block gets
      70655  consistent gets
      70616  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
          1  rows processed

通过上面的信息我们可以看到此SQL访问的block数为70655,并且基本上是物理读,其执行时间为00: 00: 10.01

大家可能一眼就看出来了,这条SQL执行了全表扫描,加索引优化就可以了,没错,索引访问正是减少SQL所需访问资源的一个主要途径
其效果也很明显
已用时间:  00: 00: 01.89

执行计划
----------------------------------------------------------
Plan hash value: 826211483

-------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |  3089   (2)| 00:00:38 |
|   1 |  SORT AGGREGATE       |         |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| I_TEST1 |  5285K|  3089   (2)| 00:00:38 |
-------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      11218  consistent gets
      11197  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

其访问的block数变为11218,其执行时间随之变为00: 00: 01.89

通过减少S,我们可以看到T得到明显的减小

上面情况是在V不变的情况下(都是物理读)的差别

再看看V最大化的结果

SQL>  select  count(*) from test;

执行计划
----------------------------------------------------------
Plan hash value: 826211483

-------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |  3089   (2)| 00:00:38 |
|   1 |  SORT AGGREGATE       |         |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| I_TEST1 |  5285K|  3089   (2)| 00:00:38 |
-------------------------------------------------------------------------

统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      11218  consistent gets
          0  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

已用时间:  00: 00: 00.79

SQL>  select /*+parallel(test 2)*/ count(*) from test;



执行计划
----------------------------------------------------------
Plan hash value: 826211483

-------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |  3089   (2)| 00:00:38 |
|   1 |  SORT AGGREGATE       |         |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| I_TEST1 |  5285K|  3089   (2)| 00:00:38 |
-------------------------------------------------------------------------


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      11218  consistent gets
          0  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

已用时间:  00: 00: 00.68

T被控制到了秒以下。

可是对于这样的一个业务11218个block的资源需求量是否也不是很合理呢,如果这个业务发生的很频繁,每次执行都需要重复扫描到相同资源并且这部分资源占总资源的绝大部分,这肯定也是很不合理的。
既然是减少S,那么减少这些重复访问的绝大部分资源理应得到更好的效果。
以上面的业务为例:
本业务的需求是实时统计表内的行数,数据都是具有生命周期的,通常情况下一个业务表内的数据大多是处于不活动状态,如此以来,预先统计好这部分数据并形成结果,每次需要统计这部分数据时直接调用结果必将大幅减少业务所需访问的资源
如本例,已知object_id小于等于13000的数据处于不活动状态
构建分析结果表
create table test_analyzed as select count(*) o_count,13000 as o_data from test where object_id<=13000;

SQL> select o_count from test_analyzed;

   O_COUNT
----------
   5242624

已用时间:  00: 00: 00.00

统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        421  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select count(*) from test where object_id>13000;

  COUNT(*)
----------
     42624

已用时间:  00: 00: 00.01


执行计划
----------------------------------------------------------
Plan hash value: 3544821501

-----------------------------------------------------------------------------
| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |         |     1 |     5 |   159   (1)| 00:00:02 |
|   1 |  SORT AGGREGATE   |         |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| I_TEST1 | 73774 |   360K|   159   (1)| 00:00:02 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID">13000)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         98  consistent gets
          0  physical reads
          0  redo size
        421  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

S变成了3+98=101,T自然也就变成不到10毫秒了

当然现实工作中,业务需求不可能就可以如此简单的加以分解,这里只是提供一个思路

性能调优是产品全生命周期的工作,一条sql的调优很可能会追溯到产品需求的定义及产品设计等环节
而在调优工作中V的提升通常是不可持续的,一定程度的提升后再想有所提高是需要付出财力的,S的提升却是很有潜力可挖的。

个人愚见,欢迎拍砖

[ 本帖最后由 anlinew 于 2008-1-23 13:09 编辑 ]
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
2#
 楼主| 发表于 2008-1-23 13:15 | 只看该作者
原帖由 jhw4048 于 2008-1-22 12:46 发表
昨天,客户来了需求要对2007年-2008年的数据进行统计,先

1.将本番数据库相关数据导入本地环境

2.先按需求写出SQL文如下
/* Formatted on 2008/01/22 12:30 (Formatter Plus v4.8.5) */
SELECT SUM (d.mileage) / MAX (ROWNUM)
  FROM (SELECT c.vinno, c.orderno, c.mileage, c.srvdate,
               ROW_NUMBER () OVER (PARTITION BY c.vinno ORDER BY c.vinno) rn
          FROM (SELECT DISTINCT a.vinno, a.orderno, a.mileage, a.srvdate
                           FROM a,
                                 b,
                                 c
                          WHERE a.dealercode = b.dealercode
                            AND a.orderno = b.orderno
                            AND a.datafrom = b.datafrom
                            AND a.vinno = c.vinno
                            AND TO_CHAR (srvdate, 'yyyy-mm-dd')
                                   BETWEEN '2007-01-01'
                                       AND '2007-12-31'
                            AND NVL (a.deleteflag, '0') != '1'
                            AND NVL (b.deleteflag, '0') != '1'
                            AND b.partscode = 'aaa'
                            AND a.dealercode = 'bbb'
                            AND c.model = 'ccc'
                       ORDER BY srvdate) c) d
WHERE d.rn = '2';

3.根据执行计划对model 字段建索引

4.对每张表进行表分析

5.因为要多次执行此SQL文以获得不同的统计数据(上万次),且每张表的数据量也很大,本人用JAVA写了个程序按客户要求循环执行以上SQL文生成数据报表,执行速度不能忍受,

5.建立物化视图
DBMS_MVIEW.EXPLAIN_REWRITE()
CREATE MATERIALIZED VIEW  SPK_PARTS_mv
ENABLE QUERY REWRITE
AS
select distinct a.vinno, a.orderno, a.MILEAGE, a.srvdate
from A,  B,  C
where a.dealercode = b.dealercode
and a.orderno = b.orderno
and a.DATAFROM = b.DATAFROM
and a.vinno = c.vinno
and to_char(srvdate, 'yyyy-mm-dd') between '2007-01-01' and '2007-12-31'
and nvl(a.deleteflag, '0') != '1'
and nvl(b.deleteflag, '0') != '1'


6.建立后发现并不能应用到SQL文中,速度仍然很慢,删除此视图,用如下重建
DBMS_MVIEW.EXPLAIN_REWRITE()
CREATE MATERIALIZED VIEW  SPK_PARTS_mv
ENABLE QUERY REWRITE
AS
select distinct a.vinno, a.orderno, a.MILEAGE, a.srvdate,a.dealercode, b.partscode, c.model
from  A,  B,  C
where a.dealercode = b.dealercode
and a.orderno = b.orderno
and a.DATAFROM = b.DATAFROM
and a.vinno = c.vinno
and to_char(srvdate, 'yyyy-mm-dd') between '2007-01-01' and '2007-12-31'
and nvl(a.deleteflag, '0') != '1'
and nvl(b.deleteflag, '0') != '1'


7.改写SQL如下
select  sum(d.mileage)/max(rownum)
from (select c.vinno, c.orderno, c.MILEAGE, c.srvdate,
row_number() over(Partition By c.vinno order by c.vinno) rn
from
(select * from (select distinct a.vinno, a.orderno, a.MILEAGE, a.srvdate,a.dealercode, b.partscode, c.model
from  A,  B,  C
where a.dealercode = b.dealercode
and a.orderno = b.orderno
and a.DATAFROM = b.DATAFROM
and a.vinno = c.vinno
and to_char(srvdate, 'yyyy-mm-dd') between '2007-01-01' and '2007-12-31'
and nvl(a.deleteflag, '0') != '1'
and nvl(b.deleteflag, '0') != '1') h
where h.dealercode = 'aaa'
and h.MODEL = 'bbb'
and h.partscode = 'ccc'
order by h.srvdate) c) d
where d.rn = '1'

8.此时再执行SQL可以看到数据已从建立的视图中获得,速度可以接受,


9.在执行程序的时候遇到新的问题,用如下SQL文根踪查看,发现开始很快,可是到后面每一个SQL文都执行的很慢
select /*+ordered*/
sql_text
from v$sqltext a
where (a.hash_value, a.address) in (
select decode (sql_hash_value,
0, prev_hash_value,
sql_hash_value
),
decode (sql_hash_value, 0, prev_sql_addr, sql_address)
from v$session b
where b.sid = '12')
order by piece asc;
查看v$session_wait,查看等待,db file sequential read DB,
因为这是本机的随便建的一个数据库,参数都设的比较小,

10.执行
SELECT name, value FROM v$sysstat WHERE name IN ('sorts (memory)', 'sorts (disk)');
查看发现比较正常
接下来执行
SELECT name,value
  FROM V$SYSSTAT
  WHERE name IN ('db block gets','consistent gets','physical reads');
用如下公式:
命中率=1-physical reads/(dbblock gets+consistent gets)
计算发现很低,分析为db_cache_size过小导致
将其增大,重启数据库,再执行正常



总结:以上为本人的亲身经历,发上来与大家共享,并请大侠们多多指正,谢谢

以另外一位puber的案例为例

通过MV,一定程度的减少了S

通过调整db_cache_size,一定程度的增大V

但是这个案例,S所减少的程度显然还不够,执行上万次,其中多数都是无用功。。。。

使用道具 举报

回复
论坛徽章:
145
生肖徽章2007版:兔
日期:2008-01-02 17:35:532010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-01-04 08:33:082009新春纪念徽章
日期:2009-01-04 14:52:282009新春纪念徽章
日期:2009-01-04 14:52:282009新春纪念徽章
日期:2009-01-04 14:52:28
3#
发表于 2008-1-23 13:20 | 只看该作者
支持楼主原创

使用道具 举报

回复
论坛徽章:
59
狮子座
日期:2016-03-26 13:35:402013年新春福章
日期:2013-02-25 14:51:24双黄蛋
日期:2013-02-25 11:06:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:20灰彻蛋
日期:2012-04-25 13:19:33紫蛋头
日期:2012-03-14 11:16:09最佳人气徽章
日期:2012-03-13 17:39:18玉石琵琶
日期:2012-02-21 15:04:38鲜花蛋
日期:2011-11-30 14:13:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
4#
发表于 2008-1-23 13:21 | 只看该作者
最后一个object_id<=13000的办法可以用mv

使用道具 举报

回复
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
5#
 楼主| 发表于 2008-1-23 13:24 | 只看该作者
原帖由 bluemoon0083 于 2008-1-23 13:21 发表
最后一个object_id

方法还是很多的,欢迎大家补充,呵呵

使用道具 举报

回复
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
6#
 楼主| 发表于 2008-1-23 13:29 | 只看该作者
mysql版的另一个案例

原帖由 cyt2005 于 2008-1-18 15:44 发表
首先这是涉及到的表的数据
mocha_humantask_task 139263
mocha_document_body 30519
mocha_bo_instance 19235
mocha_bo_definition 445
mocha_be_process_log 129276
mocha_be_process_instance 16761

接下来是sql语句
SELECT M.PACKAGEID  AS PACKAGEID, M.PROCESSID  AS PROCESSID, M.
               PROCESSDEFINEID  AS PROCESSDEFINEID, M.WORKFLOWNAME  AS
               WORKFLOWNAME, B.DOCUMENT_ID  AS DOCUMENT_ID, B.FORM_ID  AS
               FORM_ID, B.FORM_VERSION  AS FORM_VERSION, B.DOCUMENT_TITLE  AS
               DOCUMENT_TITLE, B.DOCUMENT_PRIORITY  AS DOCUMENT_PRIORITY, I1.
               STARTTIME  AS STARTTIME, I1.IDENTITYSTR  AS IDENTITYSTR, I1.
               ACTIVITYNAME  AS ACTIVITYNAME, I1.ACTIVITYID  AS ACTIVITYID, I1
               .GRANTORID  AS GRANTORID, I1.GRANTORNAME  AS GRANTORNAME, i2.
               username  AS SUBMITUSERNAME, log_ext.dead_line  AS dead_line,
               bo_inst.bo_instance_id  AS bo_instance_id, bo_def.bo_def_name  
               AS bo_def_name, bo_def.bo_def_id  AS bo_def_id, bo_def.
               bo_type_def_id  AS bo_type_def_id, i1.logid  AS logid, b.
               document_state  AS document_state, b.document_secret  AS
               document_secret, i1.is_open  AS is_open, I1.USERNAME  AS
               USERNAME, I1.Userid  AS Userid
          FROM                   mocha_document_body b
                              INNER JOIN
                                 mocha_bo_instance bo_inst
                              ON bo_inst.bo_instance_id = b.bo_instance_id
                           INNER JOIN
                              mocha_bo_definition bo_def
                           ON bo_def.bo_def_id = bo_inst.bo_def_id
                        INNER JOIN
                           mocha_be_process_instance m
                        ON m.docid = bo_inst.bo_instance_id
                     INNER JOIN
                        mocha_be_process_log i1
                     ON i1.processid = m.processid
                  INNER JOIN
                     mocha_humantask_task log_ext
                  ON i1.logid = log_ext.task_id
               LEFT OUTER JOIN
                  mocha_be_process_log i2
               ON i1.fromlogid = i2.logid AND i2.processid = m.processid
         WHERE b.document_state  300
               AND i1.work_status_id = 2
               AND bo_inst.submit_flag = 1
              AND bo_inst.save_flag = 1



业务表都不是很大,可业务需求是前台就是要查询其80%的数据,也就是数万的数据
这样的业务如何去减少S呢
目前比较常用的方法是根据一定的业务逻辑分页,不活跃的数据产生静态页面,既能减少数据库的压力,又能降低应用服务器的压力

使用道具 举报

回复
论坛徽章:
59
狮子座
日期:2016-03-26 13:35:402013年新春福章
日期:2013-02-25 14:51:24双黄蛋
日期:2013-02-25 11:06:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:20灰彻蛋
日期:2012-04-25 13:19:33紫蛋头
日期:2012-03-14 11:16:09最佳人气徽章
日期:2012-03-13 17:39:18玉石琵琶
日期:2012-02-21 15:04:38鲜花蛋
日期:2011-11-30 14:13:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
7#
发表于 2008-1-23 13:29 | 只看该作者
原帖由 anlinew 于 2008-1-23 13:15 发表

以另外一位puber的案例为例

通过MV,一定程度的减少了S

通过调整db_cache_size,一定程度的增大V

但是这个案例,S所减少的程度显然还不够,执行上万次,其中多数都是无用功。。。。

不好意思没看到
如果mv上再进一步优化加个索引什么的效果可能就更好了

使用道具 举报

回复
招聘 : Java研发
论坛徽章:
71
马上加薪
日期:2014-02-19 11:55:14蜘蛛蛋
日期:2012-12-26 18:16:01茶鸡蛋
日期:2012-11-16 08:12:48ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:网球
日期:2012-08-23 14:58:08奥运会纪念徽章:沙滩排球
日期:2012-07-19 17:28:14版主2段
日期:2012-07-07 02:21:02咸鸭蛋
日期:2012-03-23 18:17:482012新春纪念徽章
日期:2012-02-13 15:13:512012新春纪念徽章
日期:2012-02-13 15:13:51
8#
 楼主| 发表于 2008-1-23 13:31 | 只看该作者
原帖由 bluemoon0083 于 2008-1-23 13:29 发表

不好意思没看到
如果mv上再进一步优化加个索引什么的效果可能就更好了

主要问题可能是MV的粒度太细导致MV本身的block数下不来,S自然也下不来

使用道具 举报

回复
论坛徽章:
101
生肖徽章:猴
日期:2007-09-26 12:35:50复活蛋
日期:2011-07-08 14:26:172010广州亚运会纪念徽章:手球
日期:2011-05-09 10:15:122010广州亚运会纪念徽章:排球
日期:2011-04-13 11:57:232011新春纪念徽章
日期:2011-02-18 11:43:332010广州亚运会纪念徽章:射箭
日期:2011-01-21 14:58:57ITPUB9周年纪念徽章
日期:2010-10-08 09:28:522010广州亚运会纪念徽章:自行车
日期:2010-09-17 10:43:02铁扇公主
日期:2010-07-28 08:46:33ITPUB元老
日期:2009-05-12 13:23:24
9#
发表于 2008-1-23 13:31 | 只看该作者
强烈支持,对调优还处于认识阶段

使用道具 举报

回复
论坛徽章:
59
狮子座
日期:2016-03-26 13:35:402013年新春福章
日期:2013-02-25 14:51:24双黄蛋
日期:2013-02-25 11:06:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:20灰彻蛋
日期:2012-04-25 13:19:33紫蛋头
日期:2012-03-14 11:16:09最佳人气徽章
日期:2012-03-13 17:39:18玉石琵琶
日期:2012-02-21 15:04:38鲜花蛋
日期:2011-11-30 14:13:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
10#
发表于 2008-1-23 13:47 | 只看该作者
我也举个例子吧,特别是业务逻辑上的,应该去繁从简,越简单越好

网站后台原来有个功能是显示所有图片,包括已经上线的图片和还没有通过审核或者是有问题的图片,分别存放在两个表
因为要查询所有数据并按时间排序,当时开发人员做了个view把两张表union连接起来,每次都是查询view,由于最后要排序2个表的索引都不能用到全部是fts
发现问题后当即就提出这个地方一定要拆开,然后跟编辑和老板开会美其名曰增加一个新功能可以单独察看image和bad_image,当然最后皆大欢喜,他们使用起来也更方便,而且速度也上去了

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表