问题描述
嗨,汤姆,
我正在使用多个变量从表中获取列值 (显然,我正在使用INTO子句并获得具有过滤条件的一行)。
我也可以通过使用 % ROWTYPE来做到这一点。这样,它将获取所有列。
现在,问题是哪一个更快或占用更少的内存?哪个是最佳实践?
通过使用 % ROWTYPE将获取所有列,其中我可能不会在我的PLSQL代码块中使用很少的列值。仍然在获取这些价值。但是使用rowtype会保存多个变量的声明,这至少会保存LOC (这也不是问题)。
例如,
Employee表确实有10列,
ID,Emp_name,emp_code,性别,电子邮件,dep_id,雇主ID,组织代码,付款周期,地址
现在,在我的plsql代码块中,只需说我需要7列。我不需要dep_id,雇主 _id,组织 _code。
那么,我应该使用rowtype而不是创建7个不同的变量来存储这7个列值吗?
你能分享一下你对此的看法吗?
我正在使用多个变量从表中获取列值 (显然,我正在使用INTO子句并获得具有过滤条件的一行)。
我也可以通过使用 % ROWTYPE来做到这一点。这样,它将获取所有列。
现在,问题是哪一个更快或占用更少的内存?哪个是最佳实践?
通过使用 % ROWTYPE将获取所有列,其中我可能不会在我的PLSQL代码块中使用很少的列值。仍然在获取这些价值。但是使用rowtype会保存多个变量的声明,这至少会保存LOC (这也不是问题)。
例如,
Employee表确实有10列,
ID,Emp_name,emp_code,性别,电子邮件,dep_id,雇主ID,组织代码,付款周期,地址
现在,在我的plsql代码块中,只需说我需要7列。我不需要dep_id,雇主 _id,组织 _code。
那么,我应该使用rowtype而不是创建7个不同的变量来存储这7个列值吗?
你能分享一下你对此的看法吗?
专家解答
获取更多列的明显区别是你会消耗更多的内存。
还有多少?嗯,不出所料,这取决于...
如果排除的列 (大部分) 为null,则差异很小:
因此,选择所有列使用11.5mb,而排除那些为null的列则为10.7mb。不超过10,000行。
另一方面,如果您排除了包含长字符串的列,则节省的费用可能会很大:
选择子集使用相同数量的内存 (10.7mb)。但是,现在获得所有列的数量已高达近28mb,增加了很多。这也可能会影响SQL本身的性能,特别是如果它是 “复杂的” 并且需要对数据进行排序或将其写入temp。
例如,在下面的SQL中,我使用了实现提示来强制写入temp。请注意,获取所有列的SQL使用更多的读取,写入和缓冲区:
所以就我个人而言,我只会选择你需要的东西。但在许多情况下,这是调整的最后一英里。因此,除非你真的很紧张,或者有复杂的SQL来获取数据,否则我不会太担心它。通常在你的应用程序的其他地方会有更大的收益。
show_mem过程的代码:
还有多少?嗯,不出所料,这取决于...
如果排除的列 (大部分) 为null,则差异很小:
create table t as select level id, lpad('x', 20, 'x') c1, sysdate c2, sysdate c3, level c4, level c5, level c6, cast(null as varchar2(500)) c7, cast(null as varchar2(500)) c8, cast(null as varchar2(500)) c9 from dual connect by level <= 10000; exec dbms_session.FREE_UNUSED_USER_MEMORY ; declare type r_tab is table of t%rowtype index by binary_integer; all_cols r_tab; begin select * bulk collect into all_cols from t; show_mem('All cols, nulls'); end; / All cols, nulls session pga memory: 11.511 exec dbms_session.FREE_UNUSED_USER_MEMORY ; declare type r is record ( id t.id%type, c1 t.c1%type, c2 t.c2%type, c3 t.c3%type, c4 t.c4%type, c5 t.c5%type, c6 t.c6%type ); type r_t is table of r index by binary_integer; sub_cols r_t; begin select id, c1, c2, c3, c4, c5, c6 bulk collect into sub_cols from t; show_mem('Col subset, nulls'); end; / Col subset, nulls session pga memory: 10.761复制
因此,选择所有列使用11.5mb,而排除那些为null的列则为10.7mb。不超过10,000行。
另一方面,如果您排除了包含长字符串的列,则节省的费用可能会很大:
drop table t purge; create table t as select level id, lpad('x', 20, 'x') c1, sysdate c2, sysdate c3, level c4, level c5, level c6, lpad('x', 500, 'x') c7, lpad('y', 500, 'y') c8, lpad('z', 500, 'z') c9 from dual connect by level <= 10000; exec dbms_session.FREE_UNUSED_USER_MEMORY ; declare type r_tab is table of t%rowtype index by binary_integer; all_cols r_tab; begin select * bulk collect into all_cols from t; show_mem('All cols, long strings'); end; / All cols, long strings session pga memory: 27.948 exec dbms_session.FREE_UNUSED_USER_MEMORY ; declare type r is record ( id t.id%type, c1 t.c1%type, c2 t.c2%type, c3 t.c3%type, c4 t.c4%type, c5 t.c5%type, c6 t.c6%type ); type r_t is table of r index by binary_integer; sub_cols r_t; begin select id, c1, c2, c3, c4, c5, c6 bulk collect into sub_cols from t; show_mem('Col subset, long strings'); end; / Col subset, long strings session pga memory: 10.761复制
选择子集使用相同数量的内存 (10.7mb)。但是,现在获得所有列的数量已高达近28mb,增加了很多。这也可能会影响SQL本身的性能,特别是如果它是 “复杂的” 并且需要对数据进行排序或将其写入temp。
例如,在下面的SQL中,我使用了实现提示来强制写入temp。请注意,获取所有列的SQL使用更多的读取,写入和缓冲区:
set serveroutput off alter session set statistics_level = all; with rws as ( select /*+ materialize */* from t ) select count(*) from rws; select * from table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST')); PLAN_TABLE_OUTPUT SQL_ID cy1qpkps337c0, child number 1 ------------------------------------- with rws as ( select /*+ materialize */* from t ) select count(*) from rws Plan hash value: 1481629063 ------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | ------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.17 | 7560 | 5000 | 2500 | | 1 | TEMP TABLE TRANSFORMATION | | 1 | | 1 |00:00:00.17 | 7560 | 5000 | 2500 | | 2 | LOAD AS SELECT | | 1 | | 0 |00:00:00.11 | 5047 | 2500 | 2500 | | 3 | TABLE ACCESS FULL | T | 1 | 8412 | 10000 |00:00:00.03 | 2506 | 2500 | 0 | | 4 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.05 | 2507 | 2500 | 0 | | 5 | VIEW | | 1 | 8412 | 10000 |00:00:00.04 | 2507 | 2500 | 0 | | 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D708F_3B7555B | 1 | 8412 | 10000 |00:00:00.03 | 2507 | 2500 | 0 | ------------------------------------------------------------------------------------------------------------------------------------- Note ----- - dynamic statistics used: dynamic sampling (level=2) with rws as ( select /*+ materialize */id, c1, c2, c3, c4, c5, c6 from t ) select count(*) from rws; select * from table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST')); PLAN_TABLE_OUTPUT SQL_ID bzhjgyagqfq5a, child number 0 ------------------------------------- with rws as ( select /*+ materialize */id, c1, c2, c3, c4, c5, c6 from t ) select count(*) from rws Plan hash value: 1481629063 ------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | ------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.09 | 2682 | 2581 | 81 | | 1 | TEMP TABLE TRANSFORMATION | | 1 | | 1 |00:00:00.09 | 2682 | 2581 | 81 | | 2 | LOAD AS SELECT | | 1 | | 0 |00:00:00.06 | 2590 | 2500 | 81 | | 3 | TABLE ACCESS FULL | T | 1 | 8412 | 10000 |00:00:00.03 | 2506 | 2500 | 0 | | 4 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.03 | 86 | 81 | 0 | | 5 | VIEW | | 1 | 8412 | 10000 |00:00:00.03 | 86 | 81 | 0 | | 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D7090_3B7555B | 1 | 8412 | 10000 |00:00:00.01 | 86 | 81 | 0 | ------------------------------------------------------------------------------------------------------------------------------------- Note ----- - dynamic statistics used: dynamic sampling (level=2)复制
所以就我个人而言,我只会选择你需要的东西。但在许多情况下,这是调整的最后一英里。因此,除非你真的很紧张,或者有复杂的SQL来获取数据,否则我不会太担心它。通常在你的应用程序的其他地方会有更大的收益。
show_mem过程的代码:
create or replace procedure show_mem ( details varchar2 ) as begin for mem in ( select vstt.name, max( vsst.value ) value from v$sesstat vsst, v$statname vstt, v$session vses where vstt.statistic# = vsst.statistic# and vsst.sid = vses.sid and vstt.name in ( 'session pga memory' ) and vses.username is not null and vsst.sid = sys_context('USERENV', 'SID') group by vstt.name order by vstt.name ) loop dbms_output.put_line( details || ' ' || mem.name || ': ' || round((mem.value/1024/1024), 3) ); end loop; end show_mem; /复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
601次阅读
2025-04-15 17:24:06
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
586次阅读
2025-04-18 14:18:38
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
494次阅读
2025-04-08 09:12:48
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
478次阅读
2025-04-20 10:07:02
【ORACLE】记录一些ORACLE的merge into语句的BUG
DarkAthena
462次阅读
2025-04-22 00:20:37
Oracle 19c RAC更换IP实战,运维必看!
szrsu
439次阅读
2025-04-08 23:57:08
【ORACLE】你以为的真的是你以为的么?--ORA-38104: Columns referenced in the ON Clause cannot be updated
DarkAthena
437次阅读
2025-04-22 00:13:51
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
426次阅读
2025-04-17 17:02:24
火焰图--分析复杂SQL执行计划的利器
听见风的声音
371次阅读
2025-04-17 09:30:30
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
360次阅读
2025-04-15 14:48:05