{"text_format":"3","workbook":"xls","n_sheets":3,"sheets":["Sheet1","Sheet2","Sheet3"],"read":"whole","date_system":"1900","formulas":"cached_only"}

{"sheet":"Sheet1","index":0,"n_rows":30,"n_cols":10,"rows_kept":30,"flags":["formulas_cached_only"]}
["Oracle operations/options used in TPC-H queries:"]
["Oracle Operation","Oracle Option","Num Occurances in TPCH Queries","Calpont Operation","Query","Plan","Filter Tree (n/a = no where clause)","Bug","Notes","Notes Cont."]
["BUFFER          ","SORT            ",2,"Ignored","select n_nationkey, r_name from nation, region;","buffersort01.log","n/a",null,"One explaination states that Oracle is placing the named columns, in this case r_name in memory to avoid extra tablescans.  And an askTom thread stated:  The BUFFER SORT operation can be used by optimizer when it thinks that temporarily storing the input row source and sorting it by a key column might be useful in eventually doing join; this would make the join efficient in terms of IO. This is no different from an ordinary sort in terms of overhead.\n","Oracle is taking advantage of the buffer sort mechanism to copy the second row source out of its data buffers so that the run-time engine doesn’t have to keep hitting latches and re-visiting data buffers for the second row source as it processes each row from the first row source."]
["COUNT           ","STOPKEY         ",3,"Rownum will be ignored if in Select or Where clause.  Oracle will handle.","select * from nation where rownum < 10;","countstopkey01.log","select * from nation where rownum < 10\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: Column ROWNUM has not\nbeen accessed yet.",null,"Count operation where the number of rows returned is limited by the ROWNUM expression in the WHERE clause.  Oracle starts returning rows before it has read the last row, so for instance this operation can allow Oracle to limit the number of reads of a full table scan based on a given rownum expression."]
["FILTER          ","                ",4,null,"select c_name from customer c where exists (select 0 from customer where c.c_name = 'King');\n\nselect o_totalprice from orders where o_totalprice not in (select o_totalprice from orders where o_totalprice < 5000);","filter01.log\n\nfilter02.log","select c_name from customer c where exists (select 0 from customer where c.c_name = 'King')\n                   *\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: Column :B1 has not been\naccessed yet.\n\nselect o_totalprice from orders\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: No ) found in\nLNNVL(O_TOTALPRICE",null,"Operation accepting a set of rows, eliminates some of them, and returns the rest.  A \"FILTER\" operation can be very expensive because it evaluates the subquery for each row in the parent query. The subquery, when unnested can drastically improve the execution time because the \"FILTER\" operation is converted into a join (if it can be converted to a join). Be aware that \"NOT IN\" and \"NOT EXISTS\" might produce different results for \"NULL\" values.  These queries produce FILTER operations partly becuase the columns envolved in the filter are nullable.  See HASH JOIN RIGHT ANTI for a version of the second query (with o_totalprice) that allows Oracle to transform the sub-query into a join."]
["HASH            ","GROUP BY        ",8,null,"select o_custkey, count(*) from orders group by o_custkey;","hashgroupby01.log","n/a",null,"Provides a more efficient implementation of the sort algorithm for GROUP BY statements.  This operation replaces the SORT(GROUP BY) operation in limited circumstances.  If the \"_gby_hash_aggregation_enabled\" parameter is set to FALSE (default TRUE) then the HASH (GROUP BY) operation is disabled."]
["HASH            ","UNIQUE          ",1,null,"select distinct(o_custkey) from orders;","hashunique01.log","n/a",null,"Provides a more efficient implementation of the sort algorithm for DISTINCT statements.  This operation replaces the SORT(UNIQUE) operation in limited circumstances.  If the \"_gby_hash_aggregation_enabled\" parameter is set to FALSE (default TRUE) then the HASH (UNIQUE) operation is disabled."]
["HASH JOIN       ","                ",40,null,"select n1.n_name, n2.n_name from nation n1, nation n2 where n1.n_nationkey = n2.n_nationkey;","hashjoin01.log","hashjoin01.png",null,"Operation joining two sets of rows and returning the result. This join method is useful for joining large data sets of data (DSS, Batch). The join condition is an efficient way of accessing the second table.  Query optimizer uses the smaller of the two tables/data sources to build a hash table on the join key in memory. Then it scans the larger table, probing the hash table to find the joined rows.  If there is not enough memeory for the hash table, then Oracle will use temp space (disk).  http://asktom.oracle.com/tkyte/hj/hj.html (13 min. tom kyte video on hash join)  http://www.dba-oracle.com/tips_oracle_hash_joins.htm (some information on how to influence the use of hash joins)  The parameter, _hash_join_enabled, can be used to enable/disable CBO from using hash join.  The optimizer uses a hash join to join two tables if they are joined using an equijoin and if either of the following conditions are true:  1)  A large amount of data needs to be joined, 2)  A large fraction of a small table needs to be joined. ","Oracle does not recommend using the HASH_AREA_SIZE parameter unless the instance is configured with the shared server option. Oracle recommends that you enable automatic sizing of SQL working areas by setting PGA_AGGREGATE_TARGET instead. HASH_AREA_SIZE is retained for backward compatibility."]
["HASH JOIN       ","ANTI            ",2,null,"select n_name from nation where n_regionkey not in (select r_regionkey from region where r_name = 'ASIA');","hashjoinanti01.log","hashjoinanti01.png",null,"Hash (left) antijoin.  Note that the columns involved in the anti-join must both have NOT NULL constraints. Other permutations result in FILTER execution plans.  http://www.dbspecialists.com/presentations/semijoins.html (article discussing use of semi and anti join to speed up queries)"]
["HASH JOIN       ","RIGHT ANTI      ",1,null,"select o_totalprice from orders where o_totalprice not in (select o_totalprice from orders where o_totalprice < 5000 and o_totalprice is not null) and o_totalprice is not null;","hashjoinrightanti01.log","hashjoinrightanti01.png",150,"Hash right antijoin.  http://www.dbspecialists.com/presentations/semijoins.html (article discussing use of semi and anti join to speed up queries)","Bug was written up to address the fact that the two separate references to o_totalprice are not being aliased correctly in the calpont plan."]
["HASH JOIN       ","SEMI            ",2,null,"select c_name from customer c where exists (select 0 from customer where c.c_custkey = c_custkey and c_name = 'King');","hashjoinsemi01.log","hashjoinsemi01.png",null,"Hash (left) semijoin.  http://www.dbspecialists.com/presentations/semijoins.html (article discussing use of semi and anti join to speed up queries)"]
["INDEX           ","FAST FULL SCAN  ",1,null," select l_orderkey from lineitem;","indexfastfullscan01.log","n/a, but got the following error:\n\nselect l_orderkey from lineitem\n                       *\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: Column L_ORDERKEY has\nnot been accessed yet.\n\nselect l_orderkey from lineitem\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan\n\n",149,"Retrieval of all rowids (and column values) using multiblock reads. No sorting order can be defined, that is index is read in order it is stored on disk. Compares to a full table scan on only the indexed columns. Only available with the cost based optimizer.  Requres indexed column to have not null constraint, or is not null predicated to be used in the where clause.  There is a huge benefit to not reading the table rows, but there are some requirements for Oracle to invoke the fast full-index scan.  1.  All of the columns required must be specified in the index. That is, all columns in the select and where clauses must exist in the index.  2.  The query returns more than 10 percent of the rows within the index. This 10 percent figure depends on the degree of multi-block reads and the degree of parallelism.  3.  You are counting the number of rows in a table that meet a specific criterion. The fast full-index scan is almost always used for count(*) operations.  Can also be performed in parrallel."]
["INDEX           ","RANGE SCAN      ",2,null,"select l_orderkey from lineitem where l_orderkey < 500;","indexrangescan01.log","select l_orderkey from lineitem where l_orderkey < 500\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: Column L_ORDERKEY has\nnot been accessed yet.",149,"Retrieval of one or more rowids from an index. Indexed values are scanned in ascending order.  Method for accessing multiple column values You must supply AT LEAST the leading column of the index to access data via the index Can be used for range operations (e.g. > < <> >= <= between).  A non-unique index may return multiple values for the predicate col1 = 5 and will use an index range scan.  The index range scan is one of the most common access methods. During an index range scan, Oracle accesses adjacent index entries and then uses the ROWID values in the index to retrieve the table rows.  Resequence the table rows into the same physical order as the primary index can reduce disk I/O on index range scans by several orders of magnitude."]
["INDEX           ","UNIQUE SCAN     ",6,null,"select o_orderkey from orders where o_orderkey = 500;","indexuniquescan01.log","select o_orderkey from orders where o_orderkey = 500\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan: Column O_ORDERKEY has\nnot been accessed yet.",149,"Retrieval of a single rowid from an index.  Method for looking up a single key value via a unique index. Always returns a single value.  You must supply AT LEAST the leading column of the index to access data via the index, however this may return > 1 row as the uniqueness will not be guaranteed.  Non-unique index produces index range scan."]
["MERGE JOIN      ",{"$nulls":3},"select /*+ USE_MERGE (n1, n2) */ n1.n_name, n2.n_name from nation n1, nation n2 where n1.n_nationkey = n2.n_nationkey;","mergejoin01.log","mergejoin01.png",null,"Operation accepting two sets of rows, each sorted by a specific value, combining each row from one set with the matching rows from the other, and returning the result.  Sorting is an expensive operation, especially with large tables. Because of this, SMJ is often not a particularly efficient join method.  Note:  Had to use the use_merge hint, otherwise Oracle would perform a hash join by default.  The optimizer can choose a sort merge join over a hash join for joining large amounts of data if any of the following conditions are true:  1)  The join condition between two tables is not an equi-join, 2)  Because of sorts already required by other operations, the optimizer finds it is cheaper to use a sort merge than a hash join.  "]
["MERGE JOIN      ","CARTESIAN       ",2,null,"select n1.n_name, n2.n_name from nation n1, nation n2;","mergejoincartesian01.log","n/a",null,"Can result from 1 or more of the tables not having any join conditions to any other tables in the statement. Can occur even with a join and it may not be flagged as CARTESIAN in the plan.  Note that at least one of the tables must be analyzed otherwise a NESTED LOOPS execution plan is executed.  ","With Oracle 10g a hidden parameter, _optimizer_transitivity_retain, which defaults to TRUE controls how the optimizer deals with transitive closure in queries such as select n1.n_name, n2.n_name from nation n1, nation n2 where n1.n_nationkey = n2.n_nationkey and n1.n_nationkey = 2.  Prior to Oracle 10g the optimizer would have inferred that since the two tables were being equi-joined and n1.n_nationkey = 2, then n2.n_nationkey =2, so it would drop the equi-join predicate.  In 10g by default because of this parameter the equi-join predicate is retained, and a hash join is used for this query instead of a merge join cartesian."]
["MERGE JOIN      ","OUTER           ",1,null,"select /*+ USE_MERGE (n1, n2) */ n1.n_name, n2.n_name from nation n1, nation n2 where n1.n_nationkey = n2.n_nationkey(+);","mergejoinouter01.log","mergejoinouter01.png",null,"Merge join operation to perform an outer join statement.  Note:  Had to use the use_merge hint, otherwise Oracle would perform a hash join outer by default.  When an outer join cannot drive from the outer (preserved) table to the inner (optional) table, it cannot use a hash join or nested loop joins. Then it uses the sort merge outer join for performing the join operation.  The optimizer uses sort merge for an outer join:  1)  If a nested loop join is inefficient. A nested loop join can be inefficient because of data volumes, 2)  The optimizer finds it is cheaper to use a sort merge over a hash join because of sorts already required by other operations.  "]
["NESTED LOOPS    ","                ",9,null,"select /*+ USE_NL (nation, region) */ n_name, r_name from nation, region where n_regionkey = r_regionkey;","nestedloop01.log","nestedloop01.png",null,"Operation accepting two sets of rows, an outer set and an inner set. Oracle compares each row of the outer set with each row of the inner set, returning rows that satisfy a condition. This join method is useful for joining small subsets of data (OLTP). The join condition is an efficient way of accessing the second table.  For nested loops to be efficient it is important that the first row source returns as few rows as possible as this directly controls the number of probes of the second row source. Also it helps if the access method for row source 2 is efficient as this operation is being repeated once for every row returned by row source 1.  It is very important to ensure that the inner table is driven from (dependent on) the outer table. If the inner table's access path is independent of the outer table, then the same rows are retrieved for every iteration of the outer loop, degrading performance considerably. In such cases, hash joins joining the two independent row sources perform better.  ","OPTIMIZER_INDEX_CACHING parameter can be used to influence the optimizer to favor nested loops (as well as IN iterator operations).  The higher the value the less expensive index probes in conjuction with nested loops look to the optimizer.  This parameter represents the percentage of index blocks from the inner table's index that are likely to be cached during nested loop joins.  It is not used in the calculation of costs for simple index unique scans or range scans into a single table."]
["NESTED LOOPS    ","ANTI JOIN",null,null,"select o_totalprice from orders where o_totalprice not in (select /*+ NL_AJ */ o_totalprice from orders where o_totalprice < 5000 and o_totalprice is not null) and o_totalprice is not null;","transformed_nl_aj01.log","transformed_nl_aj01.png",150,"http://www.dbspecialists.com/presentations/semijoins.html (article discussing use of semi and anti join to speed up queries)","Bug was written up to address the fact that the two separate references to o_totalprice are not being aliased correctly in the calpont plan."]
["SELECT STATEMENT","                ",22,null,"select…","n/a","n/a",null,"Step representing head of the plan."]
["SORT            ","AGGREGATE       ",7,null,"select * from orders where o_orderdate not in (select min(o.o_orderdate) from orders o);\n\nselect count(*) from nation;","sortaggregate01.log (sort(aggregate) used for min function on inner query)\n\nsortaggregate02.log","sortaggregate01.png\n\nn/a",null,"Calculate aggregate totals using functions SUM,COUNT,MIN,MAX,AVG etc.  Retrieval of a single row that is the result of applying a group function to a group of selected rows.  PGA_AGGREGATE_TARGET parameter used to tune the amount of memory made available to Oracle for sort operations.  Oracle does not recommend using the SORT_AREA_SIZE parameter unless the instance is configured with the shared server option. Oracle recommends that you enable automatic sizing of SQL working areas by setting PGA_AGGREGATE_TARGET instead. SORT_AREA_SIZE is retained for backward compatibility."]
["SORT            ","GROUP BY        ",11,null,"select n_name from nation group by n_name;","Have not found simple query against tpch schema to force sort (group by) without altering session as mentioned in notes. TPC-H query 1 will produce this operation without altering the session.","n/a",null,"Operation sorting a set of rows into groups for a query with a GROUP BY clause.  In Oracle 10.2 Hash(group by) is more commonly used, but if the \"_gby_hash_aggregation_enabled\" parameter is set to FALSE (default TRUE) the sort(group by) operation will be used.  See hash (group by) notes.  Sample query will produce sort (group by) if performed in session where above session parameter can be set to FALSE.","Note:  Since in Oracle 10.2 hash(group by) is the perferred method over sort(group by), and since in Calpont we are using a separate session against the shadow applicatoin user schema, applying session parameters against the application user session will not affect the queried explain plan unless applied to the shadow application user session.  This note applies to all other session parameters as well when applied to the application user schema.  Hints will be applied for the explain plan against the shadow application user schema."]
["SORT            ","GROUP BY NOSORT ",1,null,"select o_orderkey from orders group by o_orderkey;","sortgroupbynosort01.log","n/a",null,"Group rows together based on column values. No sort is required.  If an index has been used to retrieve the data in a sorted order, then this operation is used as the sort operation has already been handled."]
["SORT            ","JOIN            ",2,null,"select /*+ USE_MERGE (n1, n2) */ n1.n_name, n2.n_name from nation n1, nation n2 where n1.n_nationkey = n2.n_nationkey;","mergejoin01.log  (same as merge join above)","mergejoin01.png",null,"Operation sorting a set of rows before a merge-join.  "]
["SORT            ","ORDER BY        ",6,null,"select n_name from nation order by n_name;","sortorderby01.log","n/a",null,"Operation sorting a set of rows for a query with an ORDER BY clause."]
["SORT            ","ORDER BY STOPKEY",3,null,"select n_name from nation where rownum < 3 order by n_name;","sortorderbystopkey01.log","select n_name from nation where rownum < 3 order by n_name\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan",null,"Sorts rows into column order. Number of rows returned is restricted using the ROWNUM pseudo-column."]
["TABLE ACCESS    ","BY INDEX ROWID  ",8,null,"select o_orderkey, o_custkey from orders where o_orderkey < 500;","tableaccessbyindexrowid01.log","select o_orderkey, o_custkey from orders where o_orderkey < 500\n                                  *\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan",null,"Retrieves rows from a table using ROWIDs from an index.  If the table is nonpartitioned and rows are located using index(es).  The rowid of a row specifies the datafile and data block containing the row and the location of the row in that block. Locating a row by specifying its rowid is the fastest way to retrieve a single row, because the exact location of the row in the database is specified.  Access by rowid does not need to follow every index scan. If the index contains all the columns needed for the statement, then table access by rowid might not occur.  This is generally the second step after retrieving the rowid from an index. The table access might be required for any columns in the statement not present in the index."]
["TABLE ACCESS    ","FULL            ",73,null,"select l_extendedprice, l_quantity from lineitem;","tableaccessfull01.log","n/a, but got the following error:\n\nselect l_extendedprice, l_quantity from lineitem\n                                        *\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan",null,"Retrieval of all rows from a table.  Performs a scan of all blocks in the table up to the high water mark.  If you have deleted all the rows then you will still read up to the HWM. Truncate resets the HWM back to the start of the table. FTS uses multiblock i/o to read the blocks from disk. Multiblock i/o is controlled by the parameter <PARAM:db_block_multi_block_read_count>.  This defaults to:  db_block_buffers / ( (PROCESSES+3) / 4 ) Maximum values are OS dependant.  Buffers from FTS operations are placed on the Least Recently Used (LRU) end of the buffer cache so will be quickly aged out. FTS is not recommended for large tables unless you are reading >5-10% of it (or so) or you intend to run in parallel.  "]
["VIEW            ","                ",9,null,"select c.c_name, o.tot_orders from customer c, (select o_custkey, count(o_orderkey) tot_orders from orders group by o_custkey) o where c.c_custkey = o.o_custkey;","view01.log","select c.c_name, o.tot_orders from customer c, (select o_custkey, count(o_orderkey) tot_orders from orders group by o_cu\nstkey) o where c.c_custkey = o.o_custkey\n*\nERROR at line 1:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan",null,"Creates an intermediate view of data.  Operation performing a view's query and then returning the resulting rows to another operation.  In some situations views can be merged into the main query, in which case you would not see this step.  Inline views are non mergable."]
["WINDOW          ","SORT            ",2,null,"select o_orderkey, o_custkey,\no_totalprice, sum(o_totalprice) over (order by o_custkey) \"running total\"\nfrom orders\norder by o_custkey;","windowsort01.log","oracle: CALUSER01@int5xe> select o_orderkey, o_custkey,\n  2  o_totalprice, sum(o_totalprice) over (order by o_custkey) \"running total\"\n  3  from orders\n  4  order by o_custkey;\nfrom orders\n     *\nERROR at line 3:\nORA-29400: data cartridge error\nInternal error accessing Calpont table or explain plan",null,"This operation is produced when analytic functions are explicitly defined in a query, or implicitly defined by Oracle in a query rewrite.  Analytic functions are designed to address problems like: Calculate a running total, Find percentages within a group, Top-N queries, Compute moving averages, and so many more.  As mentioned above, analytic functions compute an aggregate value based on a group of rows.  They differ from aggregate functions in that they return multiple rows for each group. The group of rows is called a window and is defined by an analytic clause. For each row, a sliding window of rows is defined. This window determines the range of rows used to perform the calculations for the current row. Window sizes can be based on either a physical number of rows or a logical interval such as time.  Analytic functions are the last set of operations performed in a query except for the final ORDER BY clause. All joins and all WHERE, GROUP BY, and HAVING clauses are completed BEFORE the analytic functions are processed. Therefore, analytic functions can appear only in the SELECT list or ORDER BY clause.  ","Syntax:  Analytic-Function(<Argument1>,<Argument2>,...) OVER (<Query-Partition-Clause> <Order-By-Clause> <Windowing-Clause>).  Oracle analytic functions include:  avg, sum, dense_rank, first, lag, last, lead, max, etc.  Arguments: Analytic functions take 0 to 3 arguments. Query-Partition-Clause:  The PARTITION BY clause logically breaks a single result set into N groups, according to the criteria set by the partition expressions. The words \"PARTITION\" and \"GROUP\" are used synonymously here. The analytic functions are applied to each group independently, they are reset for each group.  Order-By-Clause:  The ORDER BY clause specifies how the data is sorted within each group (PARTITION). This will definitely affect the outcome of any analytic function.  Windowing-Clause:  The windowing clause gives us a way to define a sliding or anchored window of data, on which the analytic function will operate, within a group. This clause can be used to have the analytic function compute its value based on any arbitrary sliding or anchored window within a group.  \n"]

{"sheet":"Sheet2","index":1,"n_rows":0,"n_cols":0,"rows_kept":0,"flags":["formulas_cached_only"]}

{"sheet":"Sheet3","index":2,"n_rows":0,"n_cols":0,"rows_kept":0,"flags":["formulas_cached_only"]}