Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Статистика всё портит  [new]
TRust
Member

Откуда: из самоизоляции
Сообщений: 286
Обращаюсь к бывалым админам и гуру.

Есть большая партиционированная таблица TRD. В настоящий момент в ней почти 7 миллионов строк и она постоянно растёт.
В таблице есть составной партиционированный индекс по столбцам COLLECTOR_CODE, WHAT_TO_DO, DATE_STAMP

В хранимом коде есть запрос:

select * FROM TRD
where COLLECTOR_CODE = :B1
and WHAT_TO_DO in ('I', 'C')
and DATE_STAMP between :B2 and :B3

Обычно этот запрос выбирает не более нескольких десятков-сотен строк.

Столбец COLLECTOR_CODE в настоящий момент всегда содержит только одно значение.
Распределение данных в столбце DATE_STAMP более-менее равномерно по шкале времени (селективность высокая).
В столбце WHAT_TO_DO в основном значение 'N'. Другие значения могут появиться у очень не многих записей и на очень короткое время

Чаще всего при estimate (да даже и complit) в статистику попадает только одно значение. При этом план выполнения использует составной индекс. Всё хорошо.

Однажды при сборе статистики в выборку попало 2 значения столбца WHAT_TO_DO. При этом бакет гистограммы по данному столбцу был всё равно только один.
План выполнения стал очень плохой - Full Scan по всей таблице.

После возвращения статистики предыдущего дня (с одним значением в столбце WHAT_TO_DO) план выполнения стал правильным.

Вопросы:

1. Самый насущный: как избежать в дальнейшем повторения возникшей проблемы?

2. Попутный: почему при 2-х различных значениях в статистике столбца WHAT_TO_DO имеем только 1 бакет в гистограмме (METHOD_OPT = FOR ALL COLUMNS SIZE AUTO)?

3. Теоретический:
Почему так получается, что вышеприведённый запрос дал Full Scan, а очень похожий запрос

select * FROM TRD
where COLLECTOR_CODE = :B1
and WHAT_TO_DO in (:B4, :B5)
and DATE_STAMP between :B2 and :B3

даёт всегда правильный план выполнения, использующий составной индекс?

Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
12 май 10, 12:54    [8759885]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
Andrey.L
Member

Откуда: Харьков
Сообщений: 1546
TRust
...
Обычно этот запрос выбирает не более нескольких десятков-сотен строк.

Столбец COLLECTOR_CODE в настоящий момент всегда содержит только одно значение.
Распределение данных в столбце DATE_STAMP более-менее равномерно по шкале времени (селективность высокая).
В столбце WHAT_TO_DO в основном значение 'N'. Другие значения могут появиться у очень не многих записей и на очень короткое время
...

На основании твоих слов.
ИМХО: нужен только простой индекс по полю DATE_STAMP.
12 май 10, 13:07    [8760038]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
wildwind
Member

Откуда: Москва
Сообщений: 1296
Andrey.L,

А я бы предложил индекс по NULLIF(WHAT_TO_DO, 'N'). Но это нужно код переписывать.
12 май 10, 13:34    [8760289]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18351
Andrey.L

ИМХО: нужен только простой индекс по полю DATE_STAMP.

Вариант: FBI по WHAT_TO_DO in ('I', 'C')
Вариант: собирать гистограммы по WHAT_TO_DO
12 май 10, 13:36    [8760302]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
wildwind
Member

Откуда: Москва
Сообщений: 1296
TRust
как избежать в дальнейшем повторения возникшей проблемы?

Не уверен, что это лучшее решение, но что если собрать статистику по столбцу WHAT_TO_DO с SIZE 4, а затем собирать SIZE REPEAT.
12 май 10, 13:38    [8760325]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
TRust
Member

Откуда: из самоизоляции
Сообщений: 286
wildwind
Что если собрать статистику по столбцу WHAT_TO_DO с SIZE 4, а затем собирать SIZE REPEAT.
Во-первых, я не уверен на 100%, что это поможет. Эксперементировать на боевой базе как-то неохота...

Во-вторых, я же сказал, что скорее всего при сборе статистики никаких значений в столбце WHAT_TO_DO, кроме 'N' не будет. Бакет всё равно будет один. А вот что будет, когда в статистику попадут 2 или более значений и бакетов таки будет больше одного - неизвестно (см. "Во-первых"). Я как раз спрашиваю об этом гуру. За одно пусть ответят на мой вопрос 2.
12 май 10, 14:29    [8760861]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
wurdu
Member

Откуда: Владивосток
Сообщений: 4441
Один бакет это отсутствие гистограммы. Собственно поэтому гистограммы убиваются с помощью FOR ALL COLUMNS SIZE 1. А так как при сборе статистики попало два значения, а гистограммы нет - ну он и сделал селективность 50%. Собственно из-за косяков с гистограммами METHOD_OPT => FOR ALL COLUMNS SIZE AUTO я бы не рекомендовал использовать. А совет wildwind как раз построит гистограмму и решит проблему.
12 май 10, 14:57    [8761246]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
TRust
Member

Откуда: из самоизоляции
Сообщений: 286
Сейчас прибил гвоздями параметры гистограммы для данного столбца:

DBMS_STATS.SET_TABLE_PREFS('схема','TRD','METHOD_OPT','FOR COLUMNS WHAT_TO_DO SIZE 254');
Будем ждать что теперь будет...

P.S. Кстати, в оракле баг
7479309: DBMS_STATS.SET_TABLE_PREFS FAILS WITH ORA-ORA-20001
12 май 10, 15:13    [8761400]     Ответить | Цитировать Сообщить модератору
 Статистика всё портит  [new]
TRust
Member

Откуда: из самоизоляции
Сообщений: 286
Чем дальше занимаюсь этими параметрами, тем всё чудесатее и чудесатее...

Может быть кто может прокомментировать такие результаты:

DBMS_STATS.gather_table_stats('схема','таблица',method_opt => 'FOR COLUMNS SIZE 10 столбец1 SIZE 100 столбец2 SIZE 50');
Обновляется статистика только для двух столбцов - столбец1 и столбец2. Все остальные столбцы остаются со старой статистикой (старой датой сбора статистики). Для кого тогда указание SIZE 10 ?

DBMS_STATS.gather_table_stats('схема','таблица',method_opt => 'FOR COLUMNS (столбец1,столбец2) SIZE 50');
Ни в одном столбце не обновляется статистика

Всё делаю согласно документации.
20 май 10, 14:29    [8806771]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
Филарет
Member

Откуда:
Сообщений: 539
TRust
Для кого тогда указание SIZE 10 ?

очень похоже что это просто докописатель не подчистил после копи-паста
21 май 10, 02:24    [8810777]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
для 11.1.0.7, поигрался со следующим скриптом

set echo on;

create table testt as
select level id, case when level < 2 then 1 else 2 end flag
from dual connect by level < 1000001;

alter table testt  modify flag not null;

create index testi on testt(flag);

explain plan for
select flag
from testt
where flag = 0;
select * from table(dbms_xplan.display);

begin  
  dbms_stats.gather_table_stats(USER, 'TESTT', 
                                -- estimate_percent => 100, 
                                method_opt => 'for all indexed columns size 254', 
                                cascade => TRUE);
end;
/

explain plan for
select flag
from testt
where flag = 0;
select * from table(dbms_xplan.display);

select * from user_tab_histograms where table_name = 'TESTT';

drop table testt;

+
Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 
Connected as testu
 
SQL> 
create table testt as
select level id, case when level < 2 then 1 else 2 end flag
from dual connect by level < 1000001;
 
Table created
alter table testt  modify flag not null;
 
Table altered
create index testi on testt(flag);
 
Index created
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 268773832
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    13 |     3   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TESTI |     1 |    13 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("FLAG"=1)
Note
-----
   - dynamic sampling used for this statement
 
17 rows selected
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                               -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 372809822
---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |   500K|  1464K|   508   (2)| 00:00:07 |
|*  1 |  TABLE ACCESS FULL| TESTT |   500K|  1464K|   508   (2)| 00:00:07 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("FLAG"=1)
 
13 rows selected
select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                        5484              2 
drop table testt;
 
Table dropped


Если не указывать estimate_percent => 100, то с большой вероятностью о значении 1 в столбце flag оптимизатор не узнает, и почему-то в 11.1 в отличии от 10.2 оценивает кардинальность 500к. До сбора статистики оптимизатор всегда выбирает индекс.
21 июн 10, 15:41    [8974275]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
опечатка в зарпосе flag = 0; => flag = 1; Хотя и так тоже неудачно оченивает.
21 июн 10, 15:50    [8974345]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Если gather_table_stats нахоит в таблице больше одного значения, то оптимизатор строит корректный план:

+
SQL> 
create table testt as
select level id, case when level < 2 then 1
                      when level < 2000 then 2
                 else 3 end flag
from dual connect by level < 1000001;
 
Table created
alter table testt  modify flag not null;
 
Table altered
create index testi on testt(flag);
 
Index created
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 268773832
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    13 |     3   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TESTI |     1 |    13 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("FLAG"=1)
Note
-----
   - dynamic sampling used for this statement
 
17 rows selected
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 268773832
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     3 |     3   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TESTI |     1 |     3 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("FLAG"=1)
 
13 rows selected
select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                          10              2 
TESTT                          FLAG                                                                                        5463              3 
drop table testt;
 
Table dropped
21 июн 10, 15:59    [8974460]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18351
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                estimate_percent => null, -- COMPUTE
                                method_opt => 'for all indexed columns size skewonly',
                                cascade => TRUE);
end;
/
21 июн 10, 16:07    [8974545]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
andrey_anonymous
estimate_percent => null, -- COMPUTE

Это то же самое что и 100%?
--   estimate_percent - Percentage of rows to estimate (NULL means compute).
--      The valid range is [0.000001,100].  Use the constant
--      DBMS_STATS.AUTO_SAMPLE_SIZE to have Oracle determine the
--      appropriate sample size for good statistics. This is the default.
--      The default value can be changed using set_param procedure.
21 июн 10, 16:28    [8974733]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18351
_Nikotin

Это то же самое что и 100%?

С какой целью интересуетесь?
...Вам же надо чтобы статистика надежно находила перекосы типа "иголка в тоге сена".
Никакого другого способа кроме как просмотреть все записи тут не придумать.
Альтернативой может служить FBI или set_table_stats, если Вы точно знаете какие значения флага требуют индексирования.
21 июн 10, 16:38    [8974821]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
andrey_anonymous
...Вам же надо чтобы статистика надежно находила перекосы типа "иголка в тоге сена". Никакого другого способа кроме как просмотреть все записи тут не придумать.

Я просто поделился с чем столкнулся :) , а именно что 11.1 и 10.2 по разному отрабатывают иголку в случае только одного значения которое обнаруживается при сборке статистики.
В случае когда при сборке обнаруживается два и более значений, оптимизатор корректно обрабатывает селективность "иголки".
21 июн 10, 16:52    [8975000]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
P.S. самое интересное начинает происходить, когда иголка имеет размер 50...100 на 1000000, тогда от сбора к сбору статистики будем иметь то FTS, то IRS в зависимости от того наткнётся ли сборщик на это значение или нет.
22 июн 10, 00:16    [8976906]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
wurdu
Member

Откуда: Владивосток
Сообщений: 4441
_Nikotin
Если не указывать estimate_percent => 100, то с большой вероятностью о значении 1 в столбце flag оптимизатор не узнает, и почему-то в 11.1 в отличии от 10.2 оценивает кардинальность 500к. До сбора статистики оптимизатор всегда выбирает индекс.
Важна точная версия. В 10.2.0.4 все поменялось и стало как в 11g. Histogram change
22 июн 10, 02:51    [8977080]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
wurdu,

хм...

+

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 
Connected as testu
 
SQL> 
create table testt as
select level id, case when level < 2 then 1 else 2 end flag
from dual connect by level < 1000001;
 
Table created
alter table testt  modify flag not null;
 
Table altered
create index testi on testt(flag);
 
Index created
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
----------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost  |
----------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    13 |     3 |
|   1 |  INDEX RANGE SCAN| TESTI |     1 |    13 |     3 |
----------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version
 
11 rows selected
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
----------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost  |
----------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     3 |     3 |
|   1 |  INDEX RANGE SCAN| TESTI |     1 |     3 |     3 |
----------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version
 
11 rows selected
select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                        6170              2 
drop table testt;
 
Table dropped


Но:

+

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 
Connected as testu
 
SQL> 
create table testt as
select level id, case when level < 2 then 1
                      when level < 500000 then 2
                      else 30 end flag
from dual connect by level < 1000001;
 
Table created
alter table testt  modify flag not null;
 
Table altered
create index testi on testt(flag);
 
Index created
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
----------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost  |
----------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    13 |     3 |
|   1 |  INDEX RANGE SCAN| TESTI |     1 |    13 |     3 |
----------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version
 
11 rows selected
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
-----------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost  |
-----------------------------------------------------------
|   0 | SELECT STATEMENT  |       |   234K|   688K|   414 |
|   1 |  TABLE ACCESS FULL| TESTT |   234K|   688K|   414 |
-----------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version
 
11 rows selected
select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                        2744              2 
TESTT                          FLAG                                                                                        5344             30 
drop table testt;
 
Table dropped
 
SQL> 


в 11 кардинальность оценена так же, но более удачный план:

+

Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 
Connected as testu
 
SQL> 
create table testt as
select level id, case when level < 2 then 1
                      when level < 500000 then 2
                      else 30 end flag
from dual connect by level < 1000001;
 
Table created
alter table testt  modify flag not null;
 
Table altered
create index testi on testt(flag);
 
Index created
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 268773832
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    13 |     3   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TESTI |     1 |    13 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("FLAG"=1)
Note
-----
   - dynamic sampling used for this statement
 
17 rows selected
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed
explain plan for
select flag
from testt
where flag = 1;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 268773832
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |   237K|   695K|   468   (1)| 00:00:06 |
|*  1 |  INDEX RANGE SCAN| TESTI |   237K|   695K|   468   (1)| 00:00:06 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("FLAG"=1)
 
13 rows selected
select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                        2708              2 
TESTT                          FLAG                                                                                        5502             30 
drop table testt;
 
Table dropped
 
SQL> 
22 июн 10, 11:17    [8978119]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18351
_Nikotin

Но:

begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                -- estimate_percent => 100,
                                method_opt => 'for all indexed columns size 254',
                                cascade => TRUE);
end;
/
 
PL/SQL procedure successfully completed

select * from user_tab_histograms where table_name = 'TESTT';
 
TABLE_NAME                     COLUMN_NAME                                                                      ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE
------------------------------ -------------------------------------------------------------------------------- --------------- -------------- --------------------------------------------------------------------------------
TESTT                          FLAG                                                                                        2744              2 
TESTT                          FLAG                                                                                        5344             30 
drop table testt;
 
Table dropped
 
SQL> 

А теперь снова ВОТ ТАК:
begin
  dbms_stats.gather_table_stats(USER, 'TESTT',
                                estimate_percent => null,
                                method_opt => 'for all indexed columns size skewonly',
                                cascade => TRUE);
end;
/
Что говорит?
Отож :)
Сколько можно игнорить указание compute и деланно-удивляться результатам?
22 июн 10, 13:57    [8979764]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
andrey_anonymous,

Ну не везде же compute втыкать :)
22 июн 10, 14:15    [8979935]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18351
_Nikotin
Ну не везде же compute втыкать :)

Так и перекосы такие тоже не везде...
22 июн 10, 14:33    [8980147]     Ответить | Цитировать Сообщить модератору
 Re: Статистика всё портит  [new]
wurdu
Member

Откуда: Владивосток
Сообщений: 4441
Вообще, тесты вещь тонкая и влияет слишком много факторов.К примеру, тест с 2-мя значениями flag и гистограммой. Но гистограмма тут в общем то не влияет на процесс, и можно поставить for all indexed columns size 1 - без гистограммы и результат будет тот же - 1. Потому как есть еще low_value, high_value. А вот без гистограмм и 100% - и уже корректные low_value, high_value - но нет гистограммы и 500000. Также статистика по индексу может влиять на процесс. Так что надо много чего учитывать. Ну а в 11G план конечно удачный для кривой статистики, но по факту скорее всего там проблемы с системной статистикой / параметрами.
22 июн 10, 15:26    [8980677]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить