Executing the Plan and Fetching Rows?? 执行计划和取出行? (page 78)
??? After the optimizer determines the plan and stores it in the library cache for later reuse, the next step is to actually execute the plan and fetch the rows of data that satisfy your query.? I’m going to cover much more on plan operations and how to read and understand execution plan output in the chapters ahead, but for now, let’s talk about what happens after the plan is chosen.
??? 在优化器确定计划和存储它进库缓存以备将来重用之后,下一步就是实际执行这个计划和取出满足你查询的行数据了。在后续的章节中,我将深入计划操作以及如何读和理解执行计划输出。但是现在我们谈谈关于计划选定之后发生了什么。
??? An execution plan is just a set of instructions that tell Oracle which access method to use for each
table object and which order and join method to use to join multiple table objects together.? Each step in
the plan produces a row source that is then joined with another row source until all objects have been
accessed and joined.? As rows are retrieved that satisfy the query, they must be returned from the
database to the application.? For result sets of any size, the rows that need to be returned will very likely
not all be passed to the application in a single roundtrip.? Packets of data will be transmitted from the
database and across the network until all rows ultimately arrive back to the user/requestor.??
??? 一执行计划就是一套指令集告诉Oracle哪个访问方法用于取表对象以及哪种顺序和连接方法用于把多个表对象连接在一起。计划中的每一步生成一行源,然后与另一个行源相连接,直到所有的对象被访问和连接到。被检索到的行满足查询,他们必须从数据库返回给应用。对任意大小的结果集,所需返回的行很可能不是一次往返就能传送给应用的。数据包将跨越网络从数据库发送出,直到所有的行最终返回给用户/请求者。
??? When you execute a query, what appears to you to be a single response consisting of the rows that
satisfy your query is really a series of calls executed independently.? Your query will complete? PARSE ,
BIND,? EXEC and FETCH? steps in order to complete.? One or more? FETCH? calls will occur for a query that each return a portion of the rows that satisfy the query.? Figure 2-3 shows the steps that actually occur “under the covers” when a? SELECT statement is executed.
??? 当你执行一查询,你所看到满足你查询的由返回行组成的单个响应(实际上)是一系列独立执行的(程序)调用。为了完成你的查询要完成PARSE(解析),BIND(绑定),EXEC(执行)和FETCH(取数据)步骤。若每次只返回一部分满足查询的行,一个查询将产生一次或多次FETCH调用。图2-3展示了当一SELECT语句执行时“面罩之下”的实际发生步骤。
??? The network roundtrip between the client and the database for each call will contribute to the overall response time of the statement.? There will be only one of each type of database call except for FETCH .? As previously mentioned, Oracle will need to execute as many FETCH? calls as necessary to retrieve and return all the rows required to satisfy your query.??
??? 每次调用,在客户端与数据库之间的网络往返,组成了语句响应的整体时间。除了FETCH(取数)调用外其他类型的数据库调用都只执行一次。正如前面提及的,Oracle需要执行多次FETCH调用(完成)必要的检索和返回所有的满足你查询所需的行。
??? A single? FETCH? call will access one or more blocks of data from the buffer cache.? Each time a block is accessed, Oracle will take rows from the block and return them to the client in one roundtrip.? The number of rows that are returned is a configurable setting called? arraysize.? The? arraysize? is the number
of rows that will be transmitted in a single network roundtrip, if possible.? If the size of the rows is too
large to fit in a single packet, Oracle will break up the rows into multiple packets, but even then, only a
single? FETCH? call will be needed to provide the specified number of rows.??
??? 一次FETCH调用会访问缓冲区缓存中一个或多个数据块。每访问一个块,在一趟往返中Oracle会把从块中取出的行返回给客户端。返回的行数是一个被称之为arraysize的可配置的参数。arraysize是一次网络交互所可能发送的(最大数据)行数。如果数据行太大而不能放入一个包中,Oracle拆分(数据)行到多个包中,但是即使那样,只要一次FETCH调用就能取得指定数量的行。
???? The? arraysize setting is set programmatically; how it is accomplished will depend on which calling
application environment you use.? In SQL*Plus, where the default? arraysize is 15, you change the? arraysize setting using the command SET ARRAYSIZE n.? The JDBC default is 10 and may be changed using ((OracleConnection)conn).setDefaultRowPrefetch (n).? Make sure to discover your application’s? arraysize setting and increase it as necessary.? The benefit to having a larger? arraysize is two-fold: reduction of? FETCH calls and reduction of network roundtrips.? It may not seem like much, but the impact can be quite stunning.? Listing 2-12 demonstrates how logical reads for the same query are reduced by simply changing the arraysize.? Note that logical reads are labeled as? consistent gets in the? autotrace output.
??? arraysize参数是程序设置的;它如何实现依赖于调用应用的你所使用的环境。在SQL*Plus中,arraysize默认大小是15,你使用命令SET ARRAYSIZE n改变arraysize参数。JDBC默认是10且可通过使用((OracleConnection)conn).setDefaultRowPrefetch (n)改变。务必知道你应用的arraysize参数,适当的增加它。大的arraysize的好处有两方面:减少了FETCH调用和减少了网络传送往返。可能看上去不怎么样,但是影响令人震惊。列表 2-12示例如何通过简单的改变arraysize,相同的查询逻辑读减少了。注意逻辑读在auotrace输出中标示成consistent gets。
Listing 2-12.? How Arraysize Setting Affects Logical Reads
SQL> set arraysize 15
SQL>
SQL> set autotrace traceonly statistics
SQL>
SQL> select * from order_items ;
?
Statistics
----------------------
????????? 0? recursive calls
????????? 0? db block gets
???????? 52? consistent gets
????????? 0? physical reads
????????? 0? redo size
????? 18815? bytes sent via SQL*Net to client
??????? 865? bytes received via SQL*Net from client
???????? 46? SQL*Net roundtrips to/from client
????????? 0? sorts (memory)
????????? 0? sorts (disk)
??????? 664? rows processed
?
SQL>?
SQL> set arraysize 45
SQL> /
?
Statistics
----------------------
????????? 0? recursive calls
????????? 0? db block gets
???????? 22? consistent gets
????????? 0? physical reads
????????? 0? redo size
????? 15026? bytes sent via SQL*Net to client
??????? 535? bytes received via SQL*Net from client
???????? 16? SQL*Net roundtrips to/from client
????????? 0? sorts (memory)
????????? 0? sorts (disk)
??????? 664? rows processed
??? Even for this small result set of 664 rows, the difference that increasing the arraysize? setting produces is clearly visible.? I increased the setting from 15 to 45 and reduced the logical reads from 52 to
22 and reduced the number of network roundtrips from 46 to 16!? This change had nothing to do with
the SQL statement and everything to do with how Oracle was able to access and return the rows to you.? This is just one more example of how understanding how things work can help you help Oracle use less resources and time to do what you ask of it.
??? 即使对于664行这样的小的结果集,增加arraysize参数产生的差异也是清晰可见。我把参数从15增到45而逻辑读却从52将到22且网络往返次数从46降到16!这种改变与SQL语句和Oracle如何访问、返回数据给你所作的任何事无关。这只是一个例子,让你理解怎么做才能让你帮助Oracle用最少的资源和时间完成你要求它做的事情。