Xpert 调优

Xpert 调优
-- 10046 event 可以定义 SQL TRACE 级别

/*

|| 默认的10046级别跟 SQL TRACE 一样, 另外还有一些级别:

|| level 1: SQL Tracing

|| level 4: Tracing with bind variable values

|| level 8: Tracing with wait events

|| level 12 Tracing with bind variables and wait events (4+8=12)



level 4, 12 可以看到绑定变量的值.

*/



alter session set events '10046 trace name context forever, level 4';

-- 关闭 10046, 只需要将 level 设置成 0



-- If you wish to set the 10046 event in another user's session,

-- you will need to use the DBMS_SYSTEM, The SET_EV procedure can set an event in any session

-- You will need the SID and SERIAL# of that session from V$SESSION.

-- example:

exec dbms_system.set_ev(sid,serial#,10046,12,'');



-- 另外要使用 TKPROF 来查看 trace file 生成的报告, 直接看 trace file 无法看懂
10046 event
Xpert 调优
-- Program data instantiated within a program is stored in PGA for each user, rather than in the SGA

-- 执行pl/sql程度的相关数据, 存储在PGA中, 被编译好的PL/SQL程序本身是共享的.

-- This means that each user has his own copy of program data. If a procedure declares a PL/SQL table

-- and fills it full of 1000 strings, every user who executes that procedure has his own copy of that table and its 1000 

-- strings. This characteristic does however provide you with a fair amount of flexibility 

-- to finding the delicate resource balance between CPU and memory.



-- 权限问题

-- Stored code runs under the authority of that code’s owner, not that of the schema which is executing the code. 

-- 也就是说, 存储过程执行时是创建存储过程那个用户的权限.

-- Even though stored code runs under the authority of that code’s owner, the USER function still 

-- returns the name of the schema currently connected to Oracle.



-- 执行 procedure

-- sqlplus 环境, execute calc_totals 或 exec calc_totals

-- 如果是匿名的, 直接就执行了, 比如

begin

    calc_totals;

end;



-- 执行 function, 因为 function 有返回值, 所以, 它不能直接执行, 要有个类似变量来接收函数返回值.

-- 直接执行, 可以类似这种

exec DBMS_OUTPUT.PUT_LINE (total_sales (1997))



-- 远程调用

schema_name.[package_name.]module_name@database_link_name

emp_name := full_name@new_york (:emp.employee_id);
basic
Xpert 调优
-- sql*plus 提供的session变量

-- session variable , 可以使用的数据类型 varchar2, varchar2(N), char

-- number, number(N)



varibale X varchar2(10)

EXECUTE :X := '123';

PRINT X
session varibale
Xpert 调优
-- Because stored objects are contained in tables in the data dictionary, you can use SQL itself to get information 

-- about the currently available programs. The following views are the most useful to familiarize yourself with:



/*

USER_DEPENDENCIES - The dependencies to and from objects you own

USER_ERRORS - The current set of errors for all stored objects you own.

USER_OBJECTS - The objects you own

USER_OBJECT_SIZE - The size of the objects you own

USER_SOURCE - The text source code for all objects you own

USER_TRIGGER - The database triggers you own 

*/



-- USER_DEPENDENCIES

-- Use the USER_DEPENDENCIES view to see which objects reference or depend on a particular object

SELECT referenced_name, 

       referenced_type, 

       referenced_owner, 

       referenced_link_name

  FROM user_dependencies

 WHERE name = UPPER ('&1');



-- USER_OBJECTS

-- Displaying Information About Stored Objects, 3列比较重要 OBJECT_NAME, OBJECT_TYPE, STATUS

SET PAGESIZE 66

COLUMN object_type FORMAT A20

COLUMN object_name FORMAT A30

COLUMN status FORMAT A10

BREAK ON object_type SKIP 1

SPOOL psobj.lis

SELECT object_type, object_name, status

  FROM user_objects

 WHERE object_type IN ('PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'PROCEDURE')

 ORDER BY object_type, status, object_name

/

SPOOL OFF



-- USER_OBJECT_SIZE

-- tell you about the size of your code

SET PAGESIZE 66

COLUMN name FORMAT A30

COLUMN type FORMAT A15

COLUMN source_size FORMAT 999999

COLUMN parsed_size FORMAT 999999

COLUMN code_size FORMAT 999999

TTITLE 'Size of PL/SQL Objects > 2000 Bytes'

SPOOL pssize.lis

SELECT name, type, source_size, parsed_size, code_size

  FROM user_object_size

 WHERE code_size > 2000

 ORDER BY code_size DESC

/

SPOOL OFF



-- USER_SOURCE

-- You should always maintain the source code of your programs in text files (or a development tool specifically designed

-- to store and manage PL/SQL code outside of the database).I

SELECT text 

  FROM user_source 

 WHERE name = UPPER ('&1') 

 ORDER BY line;
Check Object
Xpert 调优
-- 1. 选择驱动表, 多表连接时

-- When Oracle processes multiple tables, it must join the two tables. 

--  There are four different join methods in the Oracle database, 

-- the Nested Loop Join, the Sort-Merge Join, the Hash Join, and the Cartesian Join

-- Cartesian Join : 笛卡尔积连接

-- Sort-Merge Join: has a sort phase and a merge phase, it scans and sorts the first (driving) 

--                   table (the one specified second in the FROM clause). Next, it scans the second

--                    table (the one specified first in the FROM clause) and merges all of the rows

--                    retrieved from the second table with those retrieved from the first table.

-- Nested Loop Join: every row in the driving table and then finds matches in the second table.

--                    If there is no index on the join column, a full table scan is performed on

--                    the second table for every row in the driving table.

--                    这种的话, 如果主驱动表100W列, 而另一个表只有10列的话, 肯定是将只有10列的表设置为

--                    主驱动表比较好

-- Hash Join:     uses a hashing algorithm (hence its name) to divide the driving table's rows into

--                multiple buckets. The second table is hashed with the same algorithm.

-- 注意: 主驱动表是  is the second table in the FROM clause of the SQL statement.

-- 例如:

/*

Table TAB1  has 16,384   rows.

Table TAB2  has 4        rows.

*/

SELECT COUNT (*) FROM TAB1, TAB2         -- 4.00 seconds elapsed

                     count     phys      cr        cur      rows

                     ------    -----    -----     -----    ------

        Parse          1         0      0         0

        Execute        1         384    386       10         0

        Fetch          1         0      0         0          1



SELECT COUNT (*) FROM TAB2, TAB1 -- 37.32 seconds elapsed

                     count     phys      cr        cur      rows

                     ------    -----    -----     -----    ------

        Parse          1         0      0         0

        Execute        1         95     49247     32770      0

        Fetch          1         0      0         0          1



-- 多表查询join 时, 选择几个表之间的交集的那个表作为驱动表.

-- 多表时, 貌似 from 后的第一个表是驱动表, 或者通过交集? 看下边例子

SELECT   . . .

FROM     location L,

         category C,

         emp E

  WHERE  E.emp_no BETWEEN 1000 AND 2000

    AND  E.cat_no =  C.cat_no

    AND  E.locn   =  L.locn

-- 更高效的做法

SELECT     . . .

 FROM      emp E,

           location L,

           category C

    WHERE  E.cat_no =  C.cat_no

      AND  E.locn   =  L.locn

      AND  E.emp_no BETWEEN 1000 AND 2000
调优法则
Xpert 调优
-- 1. 高效的删除重复的行 #################################

DELETE FROM emp E

      WHERE E.rowid > (SELECT MIN(X.rowid)

                            FROM emp X

                           WHERE X.emp_no = E.emp_no);



-- 2. 一般情况下, 在列上有索引时, 选择使用 IN 或 UNION 比 OR 更好. #################################

SELECT . . .                     SELECT . . .

   FROM   location                  FROM   location

   WHERE  loc_id = 10               WHERE  loc_id = 10

   OR     region = 'MELBOURNE'      OR     loc_id = 20

                                    OR     loc_id = 30

-- 改进:

SELECT . . .                     SELECT . . .

   FROM   location                  FROM   location

   WHERE  loc_id = 10               WHERE  loc_in IN (10,20,30)

   UNION

   SELECT . . .

   FROM   location

   WHERE  region = 'MELBOURNE'



-- 3. 最小化表扫描 minimize the number of table lookups (subquery blocks) in queries, 例如: ##########

SELECT emp_name

FROM   emp

WHERE  emp_cat   = ( SELECT MAX(category)

                        FROM   emp_categories )

AND    sal_range = ( SELECT MAX(sal_range)

                        FROM   emp_categories )

AND    emp_dept  = 0020;

-- 上例中, 两个子查询是分开的, 那么需要独立扫描两次, 改进如下:

SELECT emp_name

FROM   emp

WHERE (emp_cat, sal_range)

                    = ( SELECT MAX(category), MAX(sal_range)

                        FROM   emp_categories )

AND    emp_dept  = 0020;

-- 修改的时候也一样, 参考下例:

UPDATE emp

SET    emp_cat   = ( SELECT MAX(category)

                     FROM   emp_categories ),

       sal_range = ( SELECT MAX(sal_range)

                     FROM   emp_categories )

WHERE  emp_dept  = 0020;

-- 改进

UPDATE emp

SET   (emp_cat, sal_range)

                 = ( SELECT MAX(category), MAX(sal_range)

                     FROM   emp_categories )

WHERE  emp_dept  = 0020;



-- 4. not exists 与 not in 的比较 not exists 好 ########################################

SELECT . . .

FROM   emp

WHERE  dept_no NOT IN ( SELECT dept_no

                           FROM   dept

                           WHERE  dept_cat = 'A');

-- 改进

SELECT . . .

FROM   emp E

WHERE  NOT EXISTS ( SELECT  'X'

                       FROM   dept

                       WHERE  dept_no  = E.dept_no

                       AND    dept_cat = 'A'   );

-- 5. reduce database access

-- 例如: 低效, 分别两次访问 database

SELECT emp_name, salary, grade

FROM    emp

WHERE  emp_no = 0342;



SELECT emp_name, salary, grade

FROM    emp

WHERE  emp_no = 0291;

-- 改进, 一次访问数据库

SELECT   emp_name, salary, grade,

FROM     emp A

WHERE    emp_no IN (0342,0291) ;



-- 6. 使用 * 时, 最好给表起个别名, 然后使用, 这样高效, 例如 ####################################

INSERT INTO emp_audit

SELECT USER, SYSDATE, A.*

FROM   emp A

WHERE  emp_no = :emp_no;



-- 7. union 和 union all

-- 一般如果不考虑去掉 重复的, 还有排序等内容的话, 使用 union all



-- 8. decode 可以被活用, 例如:

SELECT COUNT(*), SUM(salary)

FROM   emp

WHERE  dept_no  =  0020

AND    emp_name LIKE 'SMITH%' ;



SELECT COUNT(*), SUM(salary)

FROM   emp

WHERE  dept_no  =  0030

AND    emp_name LIKE 'SMITH%' ;

-- 改进

SELECT COUNT(DECODE(dept_no, 0020, 'X',    NULL)) D0020_kount,

       COUNT(DECODE(dept_no, 0030, 'X',    NULL)) D0030_kount,

       SUM  (DECODE(dept_no, 0020, salary, NULL)) D0020_sal,

       SUM  (DECODE(dept_no, 0030, salary, NULL)) D0030_sal

 FROM  emp

WHERE  emp_name LIKE 'SMITH%';
一般SQL调优

 

你可能感兴趣的:(XP)