Събиране на статистики.
На мен лично темата за събиране на статистики, винаги ми е била е интересна. Не за друго, а защото на базата на статистиките се определя и производителността или бързодействието на базата данни.
Естествено, не бих казъл, че съм експерт в тази област, но винаги от някъде се тръгва. За това тази тема няма да остане самотна а мисля да бъде с продължения. Като начало е добре да се спрем на основните неща при събиране на статистиките.
Първо как да събираме статистики на таблица, индекс, схема и цялата база данни. Всъщност , преди това е добре да изясним защо е нужно да събираме статистиките?
Един от ключовите моменти да имаме успех с CBO(Cost Base Optimizer) е внимателно да дефинираме и управляваме статистиките. За да може CBO да направи едно интелигентно решение за най-добрият план за изпълнение на една SQL заявка,
той трябва да е информиран за таблиците и индексите, които участват в заявката. Когато CBO знае разпределението, селективноста и главните стойности на колоните, CBO може да генерира почти винаги най-добрият план за изпълнение основан на една добре събрана информация.
В Oracle 10g съществува един пакет DBMS_STATS, който е предпочитан метод, за това че може да се изпълнява паралелно, да експортира статистиките от един на друг сървър, дълъг период за съхранение на статистиките, опростен синтаксис и мн.др. Именно за това
DBMS_STATS е предпочитан за събиране на статистиките. Този пакет има няколко метода с помощтта на които може да събирате статистиките върху конкретни обекти:
- GATHER_INDEX_STATS - Индекс статистики
- GATHER_TABLE_STATS - Таблици,колони и индекс статистики
- GATHER_SCHEMA_STATS - Статистиките за всички обекти в схемата
- GATHER_DICTIONARY_STATS - Статистиките за всички обекти в "dictionary"-то
- GATHER_DATABASE_STATS - Статистиките за всички обекти в базата данни
set timing on begin DBMS_STATS.GATHER_SCHEMA_STATS( ownname => 'SCOTT', options => 'GATHER AUTO', estimate_percent => DBMS_STATS.AUTO_SIMPLE_SIZE, method_opt => 'for all columns size repeat', cascade => TRUE); end; /
Има няколко стойности, които могат да се дадат на параметъра OPTIONS, които е добре да знаете:
- GATHER - ще аланизира отново цялата схема.
- GATHER EMPTY - аланизира само таблиците, за които няма събрани статистики.
- GATHER STALE - Само таблиците с повече от 10% промени (inserts, updates, deletes) ще бъдат аланизирани.
- GATHER AUTO - Ще аланизира отново таблиците за които няма събрани статистики, както и за таблици с остарели статистики. Всъщност това е комбинация, все едно използвате GATHER EMPTY и GATHER STALE заедно
... а за събиране на статистиките на една таблица или на индекс изпълнете следното:
set timing on begin DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'EMP', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt => 'for all columns size repeat', cascade => TRUE, degree => 5); end; / --- Example to gather index statistics set timing on begin DBMS_STATS.GATHER_INDEX_STATS( ownname => 'SCOTT', indname => 'PK_EMP', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, degree => 5); end; /
Опцията CASCADE
Когато анализирате определена таблица "cascade" опцията може да бъде използвана за да анализирате всички обекти имащи отношение към таблицата, като индексите, и таблиците свързани чрез "foreign-key constraints" .С други думи казано, чрез анализиране на една таблица вие ще извикате и анализирате и други таблици.
Събиране на статистиките по график
Събирането на статистиките по график, чрез пакета DBMS_JOB е най-лесният начин да сме сигурни че те ще са актуални. За това, може да създадете следната задача:
SET SERVEROUTPUT ON
DECLARE
l_job NUMBER;
BEGIN
DBMS_JOB.submit(l_job,
'BEGIN DBMS_STATS.gather_schema_stats(''SCOTT''); END;',
SYSDATE,
'SYSDATE + 1');
COMMIT;
DBMS_OUTPUT.put_line('Job: ' || l_job);
END;
/
Кода по-горе ще се изпълнява всеки ден по същото време, когато е стартирана за първи път задачата. Ако искате да премахнете задачата можете да използвате следната команда:
EXEC DBMS_JOB.remove(X); COMMIT;
Където Х е номера на задачата, която искате да премахнете.