sql查询中尽量减少的使用
2008-11-22 22:09
417 查看
在数据库中抓到了下面的sql,每小时执行6次,查询条件中大部分是status字段,我推断应该是监控程序,每10分钟运行一次。监控程序一般都是提取异常数据,数据量很少,要不然监控就失去意义了,像这种sql一般是要通过索引迅速定位到数据的。
原始sql:
SQL> select *
2 from tc_xx_trade t
3 where t.xx_status <> 4
4 and t.xx_status <> 5
5 and t.cs_status = 1
6 and t.timeout_type <> 'STOP_TIMEOUT'
7 and t.gmt_xiaoer_inter is not null
8 and t.gmt_xiaoer_inter < sysdate
9 and rownum < 50;
Execution Plan
--------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=9655 Card=49 Bytes=15092)
COUNT (STOPKEY)
TABLE ACCESS (FULL) OF 'TC_xx_TRADE' (Cost=9655 Card
=263124 Bytes=81042192)
Statistics
----------------------------------------------------------
1 recursive calls
1 db block gets
109922 consistent gets
101640 physical reads
120 redo size
5552 bytes sent via SQL*Net to client
656 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
sql走全表扫描,根据上面的判断我认为cs_status=1的数据量应该很小,走索引会很快。
加上hint:
SQL> select/*+index(t IDX_TC_REF_TRA_GMT_XIAOER)*/ *
2 from tc_xx_trade t
3 where t.xx_status <> 4
4 and t.xx_status <> 5
5 and t.cs_status = 1
6 and t.timeout_type <> 'STOP_TIMEOUT'
7 and t.gmt_xiaoer_inter is not null
8 and t.gmt_xiaoer_inter < sysdate
9 and rownum < 50;
Execution Plan
---------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=113996 Card=49 Bytes =15092)
0 COUNT (STOPKEY)
1 TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Cost
=113996 Card=263208 Bytes=81068064)
2 INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (NON
-UNIQUE) (Cost=32246 Card=273964)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
61745 consistent gets
34586 physical reads
65124 redo size
11553 bytes sent via SQL*Net to client
667 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
逻辑读还是很大,这表示cs_status=1的数据量应该是很多的,过滤性很差。
监控一般只会取很少的一部分数据,哪个条件具有过滤性呢,不了解业务的情况下我们只能去推测,把xx_status<>转换为 in()试试看。
<>转化为in:
SQL> select *
2 from tc_xx_trade t
3 where t.xx_status in (1, 2, 3, 6)
4 and t.cs_status = 1
5 and t.timeout_type <> 'STOP_TIMEOUT'
6 and t.gmt_xiaoer_inter is not null
7 and t.gmt_xiaoer_inter < sysdate
8 and rownum < 50;
Execution Plan
----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=541550 Card=49 Bytes =15092)
0 COUNT (STOPKEY)
1 INLIST ITERATOR
2 TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Co
st=541550 Card=1462696 Bytes=450510368)
3 INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (N
ON-UNIQUE) (Cost=4475 Card=1462696)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
898 consistent gets
0 physical reads
0 redo size
15366 bytes sent via SQL*Net to client
689 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
49 rows processed
把<>转化成in字段,效果好了很多,原理我就不多解释了,实际上和用<>不走索引,会去扫描整个表是一样的道理。
--EOF--
原始sql:
SQL> select *
2 from tc_xx_trade t
3 where t.xx_status <> 4
4 and t.xx_status <> 5
5 and t.cs_status = 1
6 and t.timeout_type <> 'STOP_TIMEOUT'
7 and t.gmt_xiaoer_inter is not null
8 and t.gmt_xiaoer_inter < sysdate
9 and rownum < 50;
Execution Plan
--------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=9655 Card=49 Bytes=15092)
COUNT (STOPKEY)
TABLE ACCESS (FULL) OF 'TC_xx_TRADE' (Cost=9655 Card
=263124 Bytes=81042192)
Statistics
----------------------------------------------------------
1 recursive calls
1 db block gets
109922 consistent gets
101640 physical reads
120 redo size
5552 bytes sent via SQL*Net to client
656 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
sql走全表扫描,根据上面的判断我认为cs_status=1的数据量应该很小,走索引会很快。
加上hint:
SQL> select/*+index(t IDX_TC_REF_TRA_GMT_XIAOER)*/ *
2 from tc_xx_trade t
3 where t.xx_status <> 4
4 and t.xx_status <> 5
5 and t.cs_status = 1
6 and t.timeout_type <> 'STOP_TIMEOUT'
7 and t.gmt_xiaoer_inter is not null
8 and t.gmt_xiaoer_inter < sysdate
9 and rownum < 50;
Execution Plan
---------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=113996 Card=49 Bytes =15092)
0 COUNT (STOPKEY)
1 TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Cost
=113996 Card=263208 Bytes=81068064)
2 INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (NON
-UNIQUE) (Cost=32246 Card=273964)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
61745 consistent gets
34586 physical reads
65124 redo size
11553 bytes sent via SQL*Net to client
667 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
逻辑读还是很大,这表示cs_status=1的数据量应该是很多的,过滤性很差。
监控一般只会取很少的一部分数据,哪个条件具有过滤性呢,不了解业务的情况下我们只能去推测,把xx_status<>转换为 in()试试看。
<>转化为in:
SQL> select *
2 from tc_xx_trade t
3 where t.xx_status in (1, 2, 3, 6)
4 and t.cs_status = 1
5 and t.timeout_type <> 'STOP_TIMEOUT'
6 and t.gmt_xiaoer_inter is not null
7 and t.gmt_xiaoer_inter < sysdate
8 and rownum < 50;
Execution Plan
----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost=541550 Card=49 Bytes =15092)
0 COUNT (STOPKEY)
1 INLIST ITERATOR
2 TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Co
st=541550 Card=1462696 Bytes=450510368)
3 INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (N
ON-UNIQUE) (Cost=4475 Card=1462696)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
898 consistent gets
0 physical reads
0 redo size
15366 bytes sent via SQL*Net to client
689 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
49 rows processed
把<>转化成in字段,效果好了很多,原理我就不多解释了,实际上和用<>不走索引,会去扫描整个表是一样的道理。
--EOF--
相关文章推荐
- SQL反模式学习笔记18 减少SQL查询数据,避免使用一条SQL语句解决复杂问题
- 执行sql语句中 为什么应该尽量减少“SELECT *”这类语句的使用
- atitit。 hb Hibernate sql 查询使用
- information_schema中Innodb相关表用于分析sql查询锁的使用情况介绍
- SQL查询中索引的使用
- 在Sql中使用like查询
- hibernate使用groupProperty,sqlGroupProjection查询,为sqlGroupProjection设置别名,用于排序
- SQL中分组函数的使用及前N条记录的查询方法
- SQL查询语句精华使用简要
- SQL查询语句精华使用简要
- SqlDictionary表,使用SQL语句查询TableID
- SQL-Server 存储过程查询速度,使用查询语句检测
- 在使用Array的时候,尽量用查询后再操作的方法,这样更加严谨.
- 使用SQL查询重复列记录
- sql语句学习笔记(9)-使用top查询指定行数(从30行至40行)
- 使用cloudera impala sql 进行交集、并集、差集查询
- Laravel SQL查询中first, pluck与lists方法的使用
- Hibernate使用sql进行查询的问题
- Hibernate使用sql进行查询的问题
- 使用SQL语句查询Mysql日志存放位置