しかし、もしも:
-あなたはすでにインデックスが使用されていることを知っています、
-リクエストの数がすでに非常に多いため、リクエストで使用するためにリクエストを分析することはできません
-追加が必要です。 クエリ実行情報
答えは非常に明白です-評価するのに非常に許容できる期間(たとえば、すべての基本的な操作が実行されるカレンダー月)の現在のサーバー操作を監視する必要があります。
これを行うには、AWRが収集するデータを使用できます。そのような使用例は、記事「ORACLE INDEX USAGE TRACKING」に記載されています。
ただし、ここですべてがうまくいくとは限りません。データベーススナップショットの取得頻度と、スナップショットの更新期間(つまり、最後のスナップショットがいつか)に依存します。 1週間または数週間のうちに特定のオブジェクトのシステムの動作を分析したい場合があり、AWRデータは過去数日間のみ保存されます。
監視には、次のアルゴリズムを使用できます。
1.興味深い情報を収集するテーブルを作成します。
2.特定の期間でタイマータスクを作成し、分析されたすべてのクエリプランの使用を監視するために、長時間要素を分析します(この例ではインデックス)。
3.期間中および期間の終わりに、タイマータスクをオフにして、結果を分析します。
4.監視の最後に、すべての監視オブジェクトを削除するか、少なくともJOBをオフにします。
以下は、説明したアルゴリズムの実装例です。
1.1。 必要なすべての権利を準備します。 sysでは、V $ SQL、V $ SQL_PLAN、V $ SQL_BIND_CAPTUREに権限を付与する必要があります(V $ SQL、V $ SQL_PLANは同義語であるため、権限を付与できないことに注意してください)。
grant select on V_$SQL to schema_name; grant select on V_$SQL_PLAN to schema_name; grant select on V$SQL_BIND_CAPTURE to schema_name;
schema_nameは、監視する回線の名前です。
1.2。 分析に役立つ情報を保存するためのテーブルを作成します。
-- V$SQL CREATE TABLE monitoring_index_usage_table as SELECT * FROM v$sql s WHERE s.hash_value IN (SELECT v.hash_value FROM v$sql_plan v WHERE v.object_name = 'XXX'); -- Add/modify columns -- Add/modify columns ALTER TABLE monitoring_index_usage_table ADD what_mon VARCHAR2(100); ALTER TABLE monitoring_index_usage_table add dt_mon date; -- Add comments to the columns COMMENT ON COLUMN monitoring_index_usage_table.what_mon is ' '; COMMENT ON COLUMN monitoring_index_usage_table.dt_mon is ' '; -- Create/Recreate indexes CREATE INDEX idx_MONITORING_INDEX_USAGE_TABLE on MONITORING_INDEX_USAGE_TABLE (sql_id); -- v$sql_plan - CREATE TABLE monitoring_index_plans AS SELECT * FROM v$sql_plan WHERE ROWNUM = 0; -- ( ) CREATE TABLE monitoring_sql_bind_capture as SELECT sql_id, name, position, datatype_string, was_captured, last_captured, value_string FROM v$sql_bind_capture WHERE sql_id = '-----';
ここで、XXXは分析中のデータベースアイテム、私の場合はインデックスであり、その名前はobject_nameになります
2.1。 テーブルを作成するプロシージャを作成します。
CREATE OR REPLACE PROCEDURE monitoring_sql_plans IS BEGIN -- , -- object_name -- -- monitoring object_name on schema_name INSERT INTO monitoring_index_usage_table SELECT s.*, 'object_name usage', SYSDATE FROM v$sql s WHERE s.last_active_time > '14.02.2012 19:20' AND s.parsing_schema_name = 'schema_name' AND (s.address, s.hash_value) IN (SELECT v.address, v.hash_value FROM v$sql_plan v WHERE v.object_name IN ('object_name') AND v.object_owner = 'schema_name') AND (address, hash_value) NOT IN (SELECT address, hash_value FROM monitoring_index_usage_table); FOR v_i IN (SELECT DISTINCT address, hash_value FROM v$sql_plan WHERE object_name IN ('object_name') AND (address, hash_value) NOT IN (SELECT address, hash_value FROM monitoring_index_plans)) LOOP INSERT INTO monitoring_index_plans SELECT * FROM v$sql_plan v WHERE v.hash_value = v_i.hash_value AND v.address = v_i.address; END LOOP; --------------------------------------------------------------------------------- -- bind FOR v_i IN (SELECT sql_id, NAME, position, datatype_string, was_captured, last_captured, value_string FROM v$sql_bind_capture WHERE sql_id IN (SELECT DISTINCT sql_id FROM monitoring_index_usage_table) AND (sql_id, last_captured) NOT IN (SELECT DISTINCT sql_id, last_captured FROM monitoring_sql_bind_capture)) LOOP INSERT INTO monitoring_sql_bind_capture VALUES (v_i.sql_id, v_i.name, v_i.position, v_i.datatype_string, v_i.was_captured, v_i.last_captured, v_i.value_string); END LOOP; END monitoring_sql_plans;
schema_nameは、データベーススキーマの名前です。
2.2。 30分に1回実行するJOBを作成します(都合の良い時間を設定します):
BEGIN sys.dbms_job.submit(job => :job, what => 'begin monitoring_sql_plans; end;', next_date => SYSDATE + 1 / 24 / 60 / 60, INTERVAL => 'SYSDATE+1/48'); COMMIT; END; /
3.さらに、随時または重要な期間の終わりに、結果を分析します。 これを行うには、いくつかの便利な異なるスライスを用意します。
SELECT round(t.cpu_time / 1000000, 2) AS time_seq, t.loads, t.executions, decode(nvl(t.executions, 0), 0, 0, round(t.cpu_time / (1000000 * t.executions), 2)) AS time_per_load, t.* FROM monitoring_index_usage_table t WHERE what_mon = 'UK_OBJ_DOC_OBJ_PROD_PART_BIRT usage' ORDER BY time_per_load DESC;
-- BIND VARIABLE SELECT * FROM monitoring_sql_bind_capture WHERE sql_id -- = '6pdbd2w2nd9w9' IN (SELECT sql_id FROM (SELECT decode(nvl(t.executions, 0), 0, 0, round(t.cpu_time / (1000000 * t.executions), 2)) AS time_per_load, t.* FROM monitoring_index_usage_table t -- 22 -- 71 12 -- 116 13 WHERE what_mon = 'object_name usage' ORDER BY time_per_load DESC) WHERE rownum = 1);
V $ SQLの説明はこちらをご覧ください 。
V $ SQL_PLANの説明はこちらをご覧ください 。
V $ SQL_BIND_CAPTUREの説明はこちらをご覧ください 。
私のニーズには、このコードで十分でした。さらに、システムで何百人ものユーザーがアクティブに作業している間でも、データベースをロードしませんでした。
この例が誰かに役立つことを願っています。
SQL_FULLTEXTを格納する個別のclobを作成する簡単な手順も作成されました。
CREATE OR REPLACE PROCEDURE mon_index_usage_get_only_sql IS n NUMBER; BEGIN -- for getting distinct sqls to table mon_index_usage_sqls -- from monitoring_index_usage_table DELETE FROM mon_index_usage_sqls; FOR v_i IN (SELECT * FROM monitoring_index_usage_table t) LOOP SELECT COUNT(*) INTO n FROM mon_index_usage_sqls s WHERE dbms_lob.compare(s.sql_fulltext, v_i.sql_fulltext) = 0; IF (n = 0) THEN INSERT INTO mon_index_usage_sqls (sql_text, sql_fulltext) VALUES (v_i.sql_text, v_i.sql_fulltext); END IF; END LOOP; END;
そしてその使用:
BEGIN -- Call the procedure mon_index_usage_get_only_sql; END; /
SELECT * FROM mon_index_usage_sqls;
4.監視が終了したら、不要なテーブルとデータからデータベースを削除することをお勧めします。
EXECUTE DBMS_JOB.REMOVE(:jobno); DROP TABLE monitoring_index_usage_table ; DROP TABLE monitoring_index_plans ; DROP TABLE monitoring_sql_bind_capture ; DROP PROCEDURE monitoring_sql_plans ; DROP PROCEDURE mon_index_usage_get_only_sql ;
結論:インデックスの使用を監視するために提案された方法を使用して、クエリプラン内のオブジェクトを、必要に応じて、必要に応じて頻繁に監視できます)))