Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

高效SQL语句编写

杨廷琨

YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD 云和恩墨 成就所托

云和恩墨成就所托
云和恩墨 成就所托
YUNHE ENMO (BEIJING) TECHNOLOGY CO.,LTD

1 合理运用新特性

2 数据集整体处理

3 设计SQL执行计划

4 严格过滤数据

云和恩墨成就所托
云和恩墨 成就所托 云和恩墨 成就所托
数据集整体处理
判断表空间是否自动扩展:
SQL> select distinct tablespace_name, autoextensible
2 from DBA_DATA_FILES
3 where autoextensible = 'YES'
4 union
5 select distinct tablespace_name, autoextensible
6 from DBA_DATA_FILES
7 where autoextensible = 'NO'
8 and tablespace_name not in
9 (select distinct tablespace_name
10 from DBA_DATA_FILES
11 where autoextensible = 'YES');

TABLESPACE_NAME AUT
------------------------------ ---
SYSAUX YES
SYSTEM YES
TEST NO
UNDOTBS1 YES
USERS YES
云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
SQL> select distinct tablespace_name, autoextensible
2 from DBA_DATA_FILES
3 where autoextensible = 'YES'
4 union
5 select distinct tablespace_name, autoextensible
6 from DBA_DATA_FILES
7 where autoextensible = 'NO'
8 and tablespace_name not in
9 (select distinct tablespace_name
10 from DBA_DATA_FILES
11 where autoextensible = 'YES');

⚫ 优点:思路清晰
⚫ 缺点:效率低效,冗余严重
• 三次扫描DBA_DATA_FILES视图
• 包含三次DISTINCT操作
• 包含UNION数据集操作
• 包含NOT IN子查询

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
SQL> SELECT TABLESPACE_NAME, MAX(AUTOEXTENSIBLE)
2 FROM DBA_DATA_FILES
3 GROUP BY TABLESPACE_NAME;

TABLESPACE_NAME MAX
------------------------------ ---
SYSAUX YES
UNDOTBS1 YES
USERS YES
TEST NO
SYSTEM YES

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
客户某执行缓慢SQL语句:
SELECT ORDER_NO, TYPE
FROM (SELECT ORDER_NO, '3' AS TYPE
FROM T_ORD_DETAIL
MINUS
SELECT ORDER_NO, '3' AS TYPE
FROM T_INA
WHERE ORDER_NO IN (SELECT ORDER_NO
FROM T_INA
WHERE CANCEL = '0'
GROUP BY ORDER_NO
HAVING COUNT(1) = 1)
AND TYPE IN ('05', '08', '10'))
UNION
SELECT ORDER_NO, TYPE
FROM (SELECT ORDER_NO, DECODE(TYPE, '05', '1', '2') AS TYPE
FROM T_INA
WHERE ORDER_NO IN (SELECT ORDER_NO
FROM T_INA
WHERE CANCEL = '0'
GROUP BY ORDER_NO
HAVING COUNT(1) = 1)
AND TYPE IN ('05', '10'));

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
SELECT *
FROM
(
SELECT ORDER_NO, MIN(TYPE) TYPE
FROM
(
SELECT ORDER_NO, '3' TYPE
FROM T_ORD_DETAIL
UNION ALL
SELECT ORDER_NO, TYPE
FROM
(
SELECT ORDER_NO,
DECODE(TYPE, '05', '1', '10', '2', '08', '0', '4') AS TYPE,
COUNT(*) OVER(PARTITION BY ORDER_NO) CN
FROM T_INA
WHERE CANCEL = '0'
)
WHERE CN = 1
AND TYPE IN ('1', '2', '0')
)
GROUP BY ORDER_NO
)
WHERE TYPE > '0';

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
SQL> CREATE TABLE T_1 AS SELECT * FROM T WHERE OWNER = 'SYS';

表已创建。

SQL> SELECT OBJECT_NAME, TYPE


2 FROM (SELECT OBJECT_NAME, 3 AS TYPE
3 FROM T_1
4 MINUS
5 SELECT OBJECT_NAME, 3 AS TYPE
6 FROM T
7 WHERE OBJECT_NAME IN (SELECT OBJECT_NAME
8 FROM T
9 WHERE GENERATED = 'Y'
10 GROUP BY OBJECT_NAME
11 HAVING COUNT(1) = 1)
12 AND OBJECT_TYPE IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW'))
13 UNION
14 SELECT OBJECT_NAME, TYPE
15 FROM (SELECT OBJECT_NAME, DECODE(OBJECT_TYPE, 'TABLE', 1, 2) AS TYPE
16 FROM T
17 WHERE OBJECT_NAME IN (SELECT OBJECT_NAME
18 FROM T
19 WHERE GENERATED = 'Y'
20 GROUP BY OBJECT_NAME
21 HAVING COUNT(1) = 1)
22 AND OBJECT_TYPE IN ('TABLE', 'MATERIALIZED VIEW'));

已选择 40879 行。

云和恩墨成就所托
成就所托
已用时间:
云和恩墨
00: 00: 05.31
数据集整体处理
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 42071 | 2834K| 1996 (2)| 00:00:01 |
| 1 | SORT UNIQUE | | 42071 | 2834K| 1996 (2)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | VIEW | | 42068 | 2834K| 1097 (2)| 00:00:01 |
| 4 | MINUS | | | | | |
| 5 | SORT UNIQUE | | 42068 | 1027K| | |
| 6 | TABLE ACCESS FULL | T_1 | 42068 | 1027K| 197 (1)| 00:00:01 |
| 7 | SORT UNIQUE | | 3 | 219 | | |
|* 8 | FILTER | | | | | |
| 9 | HASH GROUP BY | | 3 | 219 | 896 (2)| 00:00:01 |
|* 10 | HASH JOIN | | 267 | 19491 | 894 (1)| 00:00:01 |
|* 11 | TABLE ACCESS FULL| T | 8915 | 400K| 447 (1)| 00:00:01 |
|* 12 | TABLE ACCESS FULL| T | 45584 | 1201K| 447 (1)| 00:00:01 |
|* 13 | FILTER | | | | | |
| 14 | HASH GROUP BY | | 3 | 219 | 896 (2)| 00:00:01 |
|* 15 | HASH JOIN | | 267 | 19491 | 894 (1)| 00:00:01 |
|* 16 | TABLE ACCESS FULL | T | 2421 | 108K| 447 (1)| 00:00:01 |
|* 17 | TABLE ACCESS FULL | T | 45584 | 1201K| 447 (1)| 00:00:01 |
----------------------------------------------------------------------------------

13 recursive calls
0 db block gets
7069 consistent gets
0 physical reads
0 redo size
1740268 bytes sent via SQL*Net to client
30527 bytes received via SQL*Net from client
2727 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
云和恩墨40879
云和恩墨 成就所托
成就所托 rows processed
数据集整体处理
SQL> SELECT *
2 FROM
3 (
4 SELECT OBJECT_NAME, MIN(TYPE) TYPE
5 FROM
6 (
7 SELECT OBJECT_NAME, 3 TYPE
8 FROM T_1
9 UNION ALL
10 SELECT OBJECT_NAME, TYPE
11 FROM
12 (
13 SELECT OBJECT_NAME, DECODE(OBJECT_TYPE, 'TABLE', 1, 'MATERIALIZED VIEW', 2, 'VIEW', 0, 4) AS TYPE,
14 COUNT(*) OVER(PARTITION BY OBJECT_NAME) CN
15 FROM T
16 WHERE GENERATED = 'Y'
17 )
18 WHERE CN = 1
19 AND TYPE IN (1, 2, 0)
20 )
21 GROUP BY OBJECT_NAME
22 )
23 WHERE TYPE > 0;

已选择 40879 行。

已用时间: 00: 00: 03.46

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 87652 | 5906K| 654 (3)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 87652 | 5906K| 654 (3)| 00:00:01 |
| 3 | VIEW | | 87652 | 5906K| 648 (2)| 00:00:01 |
| 4 | UNION-ALL | | | | | |
| 5 | TABLE ACCESS FULL | T_1 | 42068 | 1027K| 197 (1)| 00:00:01 |
|* 6 | VIEW | | 45584 | 3650K| 451 (2)| 00:00:01 |
| 7 | WINDOW SORT | | 45584 | 1602K| 451 (2)| 00:00:01 |
|* 8 | TABLE ACCESS FULL| T | 45584 | 1602K| 447 (1)| 00:00:01 |
--------------------------------------------------------------------------------

0 recursive calls
0 db block gets
2294 consistent gets
0 physical reads
0 redo size
1740403 bytes sent via SQL*Net to client
30527 bytes received via SQL*Net from client
2727 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
40879 rows processed
云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
在5X5的方格棋盘中(如图),每行、列、斜线(斜线不仅仅包括
对角线)最多可以放两个球,如何摆放才能放置最多的球,这样的
摆法总共有几种?输出所有的摆法。
要求:用一句SQL实现。
输出格式:从方格棋盘第一行至第5行,每行从第一列到第5列依次
输出,0表示不放球,1表示放球。例如:
1001000000000000000000000。一行输出一个行号和一个解,按解所
在的列字符串顺序从大到小排序。

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
with c as
(select rownum - 1 c from dual connect by rownum <= 2),
line_seed as
(select c1.c || c2.c || c3.c || c4.c || c5.c line, c1.c c1, c2.c c2, c3.c c3, c4.c c4, c5.c c5
from c c1, c c2, c c3, c c4, c c5
where c1.c + c2.c + c3.c + c4.c + c5.c = 2
order by 1 desc)
select rownum, line1.line || line2.line || line3.line || line4.line || line5.line result
from line_seed line1, line_seed line2, line_seed line3, line_seed line4, line_seed line5
where line1.c1 + line2.c1 + line3.c1 + line4.c1 + line5.c1 = 2
and line1.c2 + line2.c2 + line3.c2 + line4.c2 + line5.c2 = 2
and line1.c3 + line2.c3 + line3.c3 + line4.c3 + line5.c3 = 2
and line1.c4 + line2.c4 + line3.c4 + line4.c4 + line5.c4 = 2
and line1.c5 + line2.c5 + line3.c5 + line4.c5 + line5.c5 = 2
and line3.c1 + line4.c2 + line5.c3 <= 2
and line2.c1 + line3.c2 + line4.c3 + line5.c4 <= 2
and line1.c1 + line2.c2 + line3.c3 + line4.c4 + line5.c5 <= 2
and line1.c2 + line2.c3 + line3.c4 + line4.c5 <= 2
and line1.c3 + line2.c4 + line3.c5 <= 2
and line1.c3 + line2.c2 + line3.c1 <= 2
and line1.c4 + line2.c3 + line3.c2 + line4.c1 <= 2
and line1.c5 + line2.c4 + line3.c3 + line4.c2 + line5.c1 <= 2
and line2.c5 + line3.c4 + line4.c3 + line5.c2 <= 2
and line3.c5 + line4.c4 + line5.c3 <= 2;

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
with c as
(select rownum - 1 c from dual connect by rownum <= 2),
lines as
(select to_number(c1.c || c2.c || c3.c || c4.c || c5.c) line
from c c1, c c2, c c3, c c4, c c5
where c1.c + c2.c + c3.c + c4.c + c5.c = 2
order by 1 desc)
select rownum,
ltrim(to_char(line1.line, '09999'))
|| ltrim(to_char(line2.line, '09999'))
|| ltrim(to_char(line3.line, '09999'))
|| ltrim(to_char(line4.line, '09999'))
|| ltrim(to_char(line5.line, '00009')) result
from lines line1, lines line2, lines line3, lines line4, lines line5
where line1.line + line2.line + line3.line + line4.line + line5.line = 22222
and ltrim(to_char(line1.line + 10*line2.line + 100*line3.line + 1000*line4.line +
10000*line5.line), '012') is null
and ltrim(to_char(10000*line1.line + 1000*line2.line + 100*line3.line + 10*line4.line +
line5.line), '012') is null;

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
SQL> with c as
2 (select rownum - 1 c from dual connect by rownum <= 2),
3 lines as
4 (select to_number(c1.c || c2.c || c3.c || c4.c || c5.c) line
5 from c c1, c c2, c c3, c c4, c c5
6 where c1.c + c2.c + c3.c + c4.c + c5.c = 2
7 order by 1 desc)
8 select ltrim(to_char(line1.line, '09999')) || chr(10)
9 || ltrim(to_char(line2.line, '09999')) || chr(10)
10 || ltrim(to_char(line3.line, '09999')) || chr(10)
11 || ltrim(to_char(line4.line, '09999')) || chr(10)
12 || ltrim(to_char(line5.line, '00009')) result
13 from lines line1, lines line2, lines line3, lines line4, lines line5
14 where line1.line + line2.line + line3.line + line4.line + line5.line = 22222
15 and ltrim(to_char(line1.line + 10*line2.line + 100*line3.line + 1000*line4.line +
10000*line5.line), '012') is null
16 and ltrim(to_char(10000*line1.line + 1000*line2.line + 100*line3.line + 10*line4.line +
line5.line), '012') is null
17 and rownum = 1;

RESULT
------------------------------------
11000
10010
00011
01100
云和恩墨 成就所托
00101 成就所托
云和恩墨
数据集整体处理
where line1.line + line2.line + line3.line + line4.line + line5.line = 22222
and ltrim(to_char(line1.line + 10*line2.line + 100*line3.line + 1000*line4.line +
10000*line5.line), '012') is null
and ltrim(to_char(10000*line1.line + 1000*line2.line + 100*line3.line + 10*line4.line +
line5.line), '012') is null

RESULT
------------------------------------
1 1 0 0 0
1 0 0 1 0
+ 0 0 0
0 1 1
1 1
0 0
0 0 1 0 1

2 2 2 2 2

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
where line1.line + line2.line + line3.line + line4.line + line5.line = 22222
and ltrim(to_char(line1.line + 10*line2.line + 100*line3.line + 1000*line4.line +
10000*line5.line), '012') is null
and ltrim(to_char(10000*line1.line + 1000*line2.line + 100*line3.line + 10*line4.line +
line5.line), '012') is null

RESULT
------------------------------------
1 1 0 0 0
1 0 0 1 0

+ 0 0 0 10
0 1 10 0
01
0
0 0 10 0 10

0 0 2 2 2 2 2 0 0

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理
where line1.line + line2.line + line3.line + line4.line + line5.line = 22222
and ltrim(to_char(line1.line + 10*line2.line + 100*line3.line + 1000*line4.line +
10000*line5.line), '012') is null
and ltrim(to_char(10000*line1.line + 1000*line2.line + 100*line3.line + 10*line4.line +
line5.line), '012') is null

RESULT
------------------------------------
1 1 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0
+ 0 0 0 1 1 0
0 1 1 0 0
0
0
0 0 1 0 1

1 2 0 0 2 2 2 0 1

云和恩墨成就所托
云和恩墨 成就所托
数据集整体处理

• 能用SQL解决的不要用PL/SQL
• 能用PL/SQL解决的不要用JAVA
• 能用JAVA解决的不要用C
• 能用单条SQL的不要用多条
• 能用单次扫描的不要多次扫描
• 利用SQL整体访问特性,避免单条处理

云和恩墨成就所托
云和恩墨 成就所托
云和恩墨成就所托
云和恩墨 成就所托 云和恩墨 成就所托

You might also like