关于 select 子句的查询
Posted
技术标签:
【中文标题】关于 select 子句的查询【英文标题】:Query regarding select clause 【发布时间】:2020-03-27 15:14:25 【问题描述】:我需要知道以下哪个查询将最快完成,考虑:
a) 两者都有相同的行,即 5 亿,并且没有任何主键和索引。
b) 表有 30 列(部门、姓名、地址、-------- 买家)
c) 两个查询都是独立执行的,并且是第一次在 Oracle 数据库中执行。
查询 1:
select * from department;
查询 2(从 30 列中选择 4 列):
select dept,name,address,buyer from department;
如果查询 2 将首先完成,谁能详细解释原因?如果它同时完成,那为什么?
【问题讨论】:
"第一次独立执行" - 但在同一个数据库中并背靠背,或至少靠近在一起 - 因此从磁盘检索到的第一个查询的数据块在第二个查询时可能仍会被缓存在他们?这可以产生很大的不同。 (然后第一个查询第二次运行速度也会快得多......)将结果从数据库服务器传输到客户端所花费的时间也可能非常不同,只是因为第一个查询有更多(来自所有这些额外的列)。 感谢您的信息! @AlexPoole 查询不会背靠背运行。我的意思是我想知道如果两个查询的结果都没有缓存,执行将如何表现。 【参考方案1】:您可以通过运行它来找出这两个查询中的哪一个更快。但是第一个可能会更慢,因为您输入了表的所有字段,并输入了 *.我认为第二种方法更好,因为通常建议只插入您需要的字段。我总是建议您编写您希望查询返回给您的字段,因为如果有一天表格改变了它的结构,您将不会有任何问题。相反,输入 *,如果有一天新字段将插入表中,您的查询将使用它们,如果它们不在后端管理,您可能会遇到问题。因此,最好只输入您需要的字段。
【讨论】:
【参考方案2】:查询将可能运行同样快,因为 Oracle 将表数据存储为行而不是单个列的方式。无论您选择一列还是所有列,Oracle 都必须从磁盘或内存中读取整行。 (而且由于 Oracle 将数据存储在 8 KB 块中,因此它可能还会读取不止一行。)
但上述说法有很多例外。以下功能可能会使选择少量列比选择所有列运行得更快:
索引 - 如果所有列都是索引的一部分,Oracle 可以像读取精简版表一样读取该索引。 物化视图 - 与索引一样,物化视图中可能会提供较小版本的表格。 LOB - 大型对象通常存储在一个单独的段中。当Oracle读取一行数据时,如果CLOB、BLOB、XML等没有被投影,Oracle就不需要访问那个单独的段。 内存列式存储 - 另一种只读取必要列的方式。 链接行 - 如果行太大而无法放入(默认 8 KB)块中,则该行将跨越多个块,并且仅读取列的子集可能会避免读取其他块。 (我不能 100% 确定这在实践中是否属实。) 结果缓存 - 如果使用结果缓存,较小的结果集更有可能留在结果缓存中。 中间结果集 - 如果查询更复杂,并且包含连接和其他操作,那么 Oracle 将只创建必要列的中间结果集。如果使用较少的列,Oracle 将使用较少的临时表空间进行排序和散列。 网络开销 - 正如 Alex Poole 指出的那样,您对这样一个简单查询的整体性能可能更多地取决于网络而不是数据库性能。有很多例外,即使是简单的查询也很难制定一般规则。正如 alby98 所指出的,在生产代码中使用 *
并不总是一个好主意。
【讨论】:
【参考方案3】:我想说它们在数据库端执行相同,但是您的客户端在“select *”版本上会遇到性能较慢的情况,因为它返回更多数据,并且您更有可能感觉到超过 500,000,000 行由于数据量大而导致的网络延迟。 这可以从客户端或 DBA_HIST_ACTIVE_SESS_HISTORY 会话的总经过时间来衡量。
【讨论】:
以上是关于关于 select 子句的查询的主要内容,如果未能解决你的问题,请参考以下文章