alter session set WORKAREA_SIZE_POLICY = auto;
create table colours as
select 'red' colour from dual
union all
select 'blue' colour from dual
union all
select 'green' colour from dual
union all
select 'orange' colour from dual
union all
select 'yellow' colour from dual
union all
select 'purple' colour from dual
union all
select 'brown' colour from dual
union all
select 'white' colour from dual
union all
select 'black' colour from dual
create table bricks as
select rownum brick_id, colour, sysdate insert_datetime, lpad ( 'x', 100, 'x' ) stuff
from colours
cross join (
select * from dual
connect by level <= 250
);
create table pens as
select rownum pen_id, colour, sysdate insert_datetime, lpad ( 'x', 100, 'x' ) stuff
from colours
cross join (
select * from dual
connect by level <= 250
);
create table bricks_indexed as
select * from bricks;
create index brick_colour_i on bricks_indexed ( colour );
alter table bricks_indexed
modify colour not null;
create or replace view complex_query as
select count ( row_id ) row_count from (
select rownum row_id, bricks.*, pens.*
from colours
join pens
on colours.colour = pens.colour
join bricks
on colours.colour = bricks.colour
order by bricks.brick_id
);
select /* init */* from complex_query;
select /* init */count ( colour ) from bricks_indexed;
您可以在 DBMS_XPlan 中查看具有 IOSTATS 格式的语句的 I/O。这会在计划中添加一个 Buffers 列
一个操作执行了多少个逻辑 I/O
计划顶部(第 0 步)报告的缓冲区是查询的总 I/O。所以这个查询做了 ~43 获取。其中绝大多数是读取 BRICKS 表,还有一些是读取 COLORS 表。
一个操作使用了多少内存?
select /*+ gather_plan_statistics */* from complex_query;
OMem 和 1Mem 数字是估计值。Used-Mem 报告它实际使用了多少内存。
数据库估计操作 8 处的 HASH JOIN 将需要 2,171Kb 的内存。但它只使用了大约一半;1,241 KB。
一个操作进行了多少次磁盘读写
alter session set workarea_size_policy = manual;
alter session set sort_area_size = 25000;
select /*+ gather_plan_statistics */ row_count from complex_query;
减少 I/O:只选择需要的值
编写查询时,最好只选择您需要的列。这减少了通过网络从数据库发送到客户端的数据量。它可以使排序和分组等操作更加高效。
这两个查询获取表中的前 25 行,按颜色排序。但第一个获取表中的所有列。第二个只获取颜色值:
select /*+ gather_plan_statistics */*
from bricks
order by colour
fetch first 25 rows only;
select /*+ gather_plan_statistics */ colour
from bricks
order by colour
fetch first 25 rows only;
和上边的对比
减少 I/O:创建新的数据结构
全表扫描读取表中的所有行。如果表存储数百万行,如果您的查询只读取几行,这将导致大量工作浪费。您可以创建或更改数据结构以使数据库能够更有效地读取行。
最常见的方法是创建索引!这些可以帮助数据库快速找到几行。
这两个查询显示了索引可以具有的力量。BRICKS 和 BRICKS_INDEXED 表存储相同的行。但是第二个表在 COLOUR 上有一个索引。因为查询只选择 COLOUR,所以数据库能够通过读取索引而不是表来回答第二个查询:
select /*+ gather_plan_statistics */
colour, count(*)
from bricks_indexed
group by colour
order by colour;
select segment_name, segment_type, bytes
from user_segments
where segment_name in (
'BRICKS', 'BRICKS_INDEXED', 'BRICK_COLOUR_I'
);
减少 I/O:过滤器与访问谓词
select /*+ gather_plan_statistics */
count(*)
from bricks
where colour = 'red'
select /*+ gather_plan_statistics */
count(*)
from bricks_indexed
where colour = 'red';
运行此查询并获取其执行统计信息:
select /*+ gather_plan_statistics */ *
from colours c
join bricks b
on c.colour = b.colour
order by b.colour
fetch first 10 rows only;