日期:2014-05-16  浏览次数:20485 次

大数据量(千万级)查询优化实践经验
首先,一个表数据超过8千万条,而且还在以每5分钟5000条记录(不一定就是5000)增加中。
其次,该表有个字段有记录了时间。
再次,该表拥有80几个字段。

需求是:80几个字段中,要求查出50个字段,而且要求分页显示。根据需求写出的sql(样品语句)如下:

select *
  from ((select t1.*, rownum t1rownum
           from (select ddatetime,
                        obtid,
                        prediction_time,
                        make_time,
                        forecaster,
                        temperature,
                        relative_humidity,
                        wind_direction,
                        wind_speed,
                        pressure,
                        precipitation,
                        total_cloud_amount,
                        low_cloud_amount,
                        weather_type,
                        visibility,
                        min_temp_24,
                        max_temp_24,
                        min_hum_24,
                        max_hum_24,
                        precipitation_12,
                        precipitation_24,
                        total_cloud_12,
                        low_cloud_12,
                        weather_type_12,
                        wind_direction_12,
                        wind_speed_12
                   from T_SEVP_GIFT d
                  where 1 = 1and
                  to_char(d.ddatetime, 'yyyy-MM-dd hh24:mi') >= ?
                    and to_char(d.ddatetime, 'yyyy-MM-dd hh24:mi') <= ?) t1
          where rownum <= ?))
 where t1rownum >= ?



从点击到结果显示到页面总共用时511.969s,相当的慢。
该表建有索引,就是日期字段的索引。按理来说,不应该慢的啊,
经过高人指点,后来得知,使用to_char()引擎放弃使索引,511.969s也就是这么来的。但问题来了,为什么to_char()会使引擎放弃使用索引呢?
结合创建索引的最适规则,二叉查找树查找节点的算法以及适用二叉查找树的最适规则,类型匹配等等,就很容易想清楚了,to_char()函数会使数据类型丢失,索引自然就不能用了。

把to_char()改为to_date(),就能够使用索引了。

改后的sql
   select *
  from ((select t1.*, rownum t1rownum
           from (select ddatetime,
                        obtid,
                        wdidf,
                        wd2df,
                        wd2dd,
                        wd10df,
                        wd10dd,
                        wd3smaxdf,
                        wd3smaxdd,
                        wd3smaxtime,
                        wd10maxdf,
                        wd10maxdd,
                        wd10maxtime,
                        wd3daymax,
                        wf3daymax,
                        wd3daymaxtime,
                        wd10daymax,
                        wf10daymax,
                        wd10daymaxtime,
                        t,
                        maxt,
                        maxttime,
                        mint,
                        minttime,
                        daymaxt,
                        daymaxttime,
                        daymint,
                        dayminttime,
                        rh,
                        maxrh,
                        maxrhtime,
                        minrh,
                        minrhtime,
                        dp,
                        p,
                        maxp,
                        maxptime,
                        minp,
                        minptime,
                        hourrf,
                        dayrf,
                        rfmark1,
                        minrf,
                        wpv,
                        othfields,
                        rddatetime,
                        procsts
                   from T_OBTMIND d
                  where d.ddatetime >=
                        to_date('2011-09-01 10:35', 'yyyy-MM-dd hh24:mi')
                    and d.ddatetime <=
                        to_date('2011-09-01 10:38', 'yyyy-MM-dd hh24:mi')) t1
          where rownum <= 10))
 where t1rownum >= 1
--样品语句。


注意:这里只是很粗略的说了查询优化方案,具体上的优化更具实践性。比如说索引该如何建,以哪个字段建索引,索引该如何用效使用起来,索引的成本多大,该不该建等等。除了索引,还有具他办法么?