Модераторы: LSD

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Join индексирование 
:(
    Опции темы
setnull
Дата 16.6.2009, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: 1
Всего: 1



Все здравствуйте!

Есть внешний ключ. Допустимо пустое значение. Пустое значение логически соответствует принадлежности всем записям родительской таблицы.

Условие присоединения
Код

... PAR_TABLE
INNER JOIN CHILD_TABLE ON 
        CHILD_TABLE.PAR IS NULL OR CHILD_TABLE.PAR = PAR_TABLE."ID"


делает выборку по таблице CHILD_TABLE FULL SCAN и она получается не индексированной.

Что можно сделать?

Спасибо!!!!
PM MAIL   Вверх
Zloxa
Дата 16.6.2009, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(setnull @  16.6.2009,  11:49 Найти цитируемый пост)
Пустое значение логически соответствует принадлежности всем записям родительской таблицы.

кхе...  в топку бы такое smile
Цитата(setnull @  16.6.2009,  11:49 Найти цитируемый пост)
Что можно сделать?

под стать дизайну и решение.
Для того чтобы значение индекса не принимало не определенные значение - используем составной индекс, в который добавляем любое нот нулл поле, в результате получаем возможность индексного доступа по null.
Код

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 

create table par(id primary key) as select level from dual connect by level <=1e5;
 
Table created
create table child(id primary key,par_id) as select level,decode(mod(level,1e5),0,cast(null as number),mod(level,1e5)+1) from dual connect by level <= 1e6;
 
Table created
create index child$par_id on child(par_id,id);
 
Index created

explain plan for
 select *
   from par
   inner join child on child.par_id is null
                       or child.par_id = par.id
 where par.id = :val;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2063622911
--------------------------------------------------------------------------------
| Id  | Operation           | Name         | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |              |   430 | 16770 |    78   (2)| 00:00:
|   1 |  CONCATENATION      |              |       |       |            |
|   2 |   NESTED LOOPS      |              |    13 |   507 |     3   (0)| 00:00:
|*  3 |    INDEX UNIQUE SCAN| SYS_C0034093 |     1 |    13 |     1   (0)| 00:00:
|*  4 |    INDEX RANGE SCAN | CHILD$PAR_ID |    13 |   338 |     2   (0)| 00:00:
|   5 |   NESTED LOOPS      |              |   417 | 16263 |    75   (2)| 00:00:
|*  6 |    INDEX UNIQUE SCAN| SYS_C0034093 |     1 |    13 |     1   (0)| 00:00:
|*  7 |    INDEX RANGE SCAN | CHILD$PAR_ID |   417 | 10842 |    74   (2)| 00:00:
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("PAR"."ID"=TO_NUMBER(:VAL))
   4 - access("CHILD"."PAR_ID"="PAR"."ID")
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   6 - access("PAR"."ID"=TO_NUMBER(:VAL))
   7 - access("CHILD"."PAR_ID" IS NULL)
       filter(LNNVL("CHILD"."PAR_ID"="PAR"."ID"))
Note
-----
   - dynamic sampling used for this statement
 
27 rows selected
 
SQL>




--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
setnull
Дата 16.6.2009, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: 1
Всего: 1



 smile 
Пример работает
Делаю все точно так же!!!!
В моей таблице - FULLL!!!!


Может еще нужно планы как-то инвалиднуть?
PM MAIL   Вверх
Zloxa
Дата 16.6.2009, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



может для твоего случая фуллскан эффективнее? smile)
Для примера я специально выбирал именно такое сочетание данных чтобы на моем окружении индексный доступ  был эффективнее.

Добавлено через 45 секунд
Статистику после индексирования собирал?


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
setnull
Дата 16.6.2009, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: 1
Всего: 1



Собирать - это строить или смотреть?
как это сделать?
PM MAIL   Вверх
Zloxa
Дата 16.6.2009, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161





--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
setnull
Дата 18.6.2009, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: 1
Всего: 1



Цитата(Zloxa @ 16.6.2009,  15:26)
может для твоего случая фуллскан эффективнее? smile)
Для примера я специально выбирал именно такое сочетание данных чтобы на моем окружении индексный доступ  был эффективнее.

Статистику еще не собирал...
Но у меня возник вопрос. Это сарказм, или такое действительно может быть, что полное сканирование эффективнее?

Делаю выборку по значению -  индексирует
По is null - индексирует

по значению или is null - full scan, при этом выбираются 18,33% записей
PM MAIL   Вверх
DimW
Дата 18.6.2009, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 23
Всего: 44



Цитата(setnull @  18.6.2009,  10:03 Найти цитируемый пост)
Это сарказм, или такое действительно может быть, что полное сканирование эффективнее?

Цитата(setnull @  18.6.2009,  10:03 Найти цитируемый пост)
по значению или is null - full scan, при этом выбираются 18,33% записей 

если 18% от 1000 записей в таблице, то скорей всего так и есть. если их все же на порядок больше, то можно предположить что оптимайзер об этом незнает, в этом случае стоит собрать статистику, а потом разбираться.
PM MAIL ICQ   Вверх
Zloxa
Дата 18.6.2009, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(setnull @  18.6.2009,  10:03 Найти цитируемый пост)
Это сарказм, или такое действительно может быть, что полное сканирование эффективнее?

Это не сарказм.

При принятии решения о том, что выгоднее - фуллскан+хэш джойн или нестед луп +  доступ по индексу учитывается очень большое количества параметров. Как то: количество блоков в таблице, стоимость операции многблочного чтения, стоимость одноблочного чтения, кластеризация индекса, отношение стоимостей IO и CPU...

Мой опыт показывает, что я ошибаюсь в своем представлении об эффективности плана намного чаще чем оптимизатор при наличии достоверной статистики. Самостоятельно влиять на план выполнения приходится только тогда, когда я заведомо знаю больше оптимизатора. При этом, до сих пор в продуктивных решениях мне удавалось обходиться лишь двумя хинтами - first_rows & cardinality. При том, оба эти хинта - хинты оптимизатора.

Добавлено @ 11:27
Цитата(setnull @  18.6.2009,  10:03 Найти цитируемый пост)
по значению или is null - full scan, при этом выбираются 18,33% записей 

Следует учитывать что оптимизатор смотрит на значение при расчете селективности, только в сулчае, если это значение присутсвтует в гистограмме, в противном случае он принимает за селективность количество уникальных/ количество всего.
Как в этом случае будет оцениваться Null, мне не известно.
Вообще,я уже говорил что исползование null как значения - дурная практика, со всеми вытекающими. Null таки это "отсутствие значения"

Это сообщение отредактировал(а) Zloxa - 18.6.2009, 11:44


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
v2v
Дата 19.6.2009, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: 1
Всего: 56



У Тома Кайта видел пример сканирования по индеку при условии is (not) null, при том что не осуществляется сбор статистики.
Он предлагает индексировать не колонку, а функцию:  nvl(НАЗВАНИЕ_КОЛОНКИ,АЛЬТЕРНАТИВНОЕ_ЗНАЧЕНИЕ) .
Я попробовал воспроизвести такой пример, но без дополнительной хинтовки, он всё равно делает селект без индекса:
Код

create table t1(f1 number, f2 number);
alter table t1 add constraint t1#pk primary key(f1);

create index t1#i1 on t1 (nvl(f2,-1));

select /*+index(t1 t1#i1)*/* from t1 where nvl(f2,-1) = nvl(:a,-1);



--------------------
PM   Вверх
Zloxa
Дата 19.6.2009, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(v2v @  19.6.2009,  13:59 Найти цитируемый пост)
Я попробовал воспроизвести такой пример, но без дополнительной хинтовки, он всё равно делает селект без индекса:

Для твоего примера у меня индекс используется и без хинта и без статистики (10.2.0.3, 9.2.0.8).
Однако отбор - это отбор.

А ты вот попробуй join по FBI сделать smile
У меня лично не получилось. Как грится хинтуй - не хинтуй, а в плане один .... smile)

Это сообщение отредактировал(а) Zloxa - 19.6.2009, 14:38


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Zloxa
Дата 19.6.2009, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(Zloxa @  19.6.2009,  14:35 Найти цитируемый пост)
У меня лично не получилось

Гоню...
получилось ;)
Код

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 
 
create table par(id primary key check (id != -1)) as select level from dual connect by level <=1e5;
 
Table created
create table child(id primary key,par_id) as select level,decode(mod(level,1e5),0,cast(null as number),mod(level,1e5)+1) from dual connect by level <= 1e6;
 
Table created
create index child$par_id$fbi on child (nvl(par_id,-1));
 
Index created
analyze table par compute statistics;
 
Table analyzed
analyze table child compute statistics for all columns;
 
Table analyzed
explain plan for
 select
   *
   from par
   inner join child on nvl(child.par_id, -1) in(par.id,-1)
 where par.id = :val;
 
Explained
select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 158516727
--------------------------------------------------------------------------------
| Id  | Operation                         | Name             | Rows  | Bytes | C
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                  |    32 |   384 |
|   1 |  NESTED LOOPS                     |                  |    32 |   384 |
|*  2 |   INDEX UNIQUE SCAN               | SYS_C0034125     |     1 |     4 |
|   3 |   TABLE ACCESS BY INDEX ROWID     | CHILD            |    32 |   256 |
|   4 |    BITMAP CONVERSION TO ROWIDS    |                  |       |       |
|   5 |     BITMAP OR                     |                  |       |       |
|   6 |      BITMAP CONVERSION FROM ROWIDS|                  |       |       |
|*  7 |       INDEX RANGE SCAN            | CHILD$PAR_ID$FBI |       |       |
|   8 |      BITMAP CONVERSION FROM ROWIDS|                  |       |       |
|*  9 |       INDEX RANGE SCAN            | CHILD$PAR_ID$FBI |       |       |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   2 - access("PAR"."ID"=TO_NUMBER(:VAL))
   7 - access("PAR"."ID"=NVL("PAR_ID",(-1)))
   9 - access(NVL("PAR_ID",(-1))=(-1))
Note
-----
   - dynamic sampling used for this statement
 
27 rows selected
 



--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
v2v
Дата 19.6.2009, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: 1
Всего: 56



Цитата(Zloxa @  19.6.2009,  14:35 Найти цитируемый пост)

Для твоего примера у меня индекс используется и без хинта и без статистики (10.2.0.3, 9.2.0.8).

10.2.0.4 - фул скан и ничего не могу поделать.

Добавлено @ 18:07
Цитата(Zloxa @  19.6.2009,  15:11 Найти цитируемый пост)
Index created
analyze table par compute statistics;

но если со статитикой , как  у тебя по джойну то получается ...

Это сообщение отредактировал(а) v2v - 19.6.2009, 18:07


--------------------
PM   Вверх
setnull
Дата 23.6.2009, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: 1
Всего: 1



Код

inner join child on nvl(child.par_id, -1) in(par.id,-1)

я такое, если не ошибаюсь, поробовал раньше. При это в плане это разивается на два условия

nvl(child.par_id, -1) = par.id
or nvl(child.par_id, -1) =-1

но при этом все равно остается фулскан...

Цитата

analyze table par compute statistics;
analyze table child compute statistics for all columns;


Это директивы или консольный вывод?

И вообще, где можно достать полезную информацию о механизмах планирования и оптимизации. Все, с чем я сталкивался до этого -  очень общие понятия (Оракл делает планы, и потом ими пользуется). Но при этом я не имею целостного представления о том, что, где и когда делает Оракл? Что, где и когда может анализировать разработчик, а также чем, где и когда он может пользоваться, чтоб работа всего этого механизма происходила эффективно ?


Спасибо!!!
PM MAIL   Вверх
Zloxa
Дата 23.6.2009, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 37
Всего: 161



Цитата(setnull @  23.6.2009,  13:00 Найти цитируемый пост)
И вообще, где можно достать полезную информацию о механизмах планирования и оптимизации.

Oracle® Database Performance Tuning Guide
Цитата(setnull @  23.6.2009,  13:00 Найти цитируемый пост)
Это директивы или консольный вывод?

ANALYZE
Цитата

Note:
Do not use the COMPUTE and ESTIMATE clauses of ANALYZE to collect optimizer statistics. These clauses are supported for backward compatibility. Instead, use the DBMS_STATS package, which lets you collect statistics in parallel, collect global statistics for partitioned objects, and fine tune your statistics collection in other ways.

Цитата(setnull @  23.6.2009,  13:00 Найти цитируемый пост)
поробовал раньше.

1)Индекс по функции при том строил?
2)Статистика по индексу,(таблице) после построения индекса собиралась?
3)Системная статистика вообще когданибудь собиралась?
Цитата(setnull @  23.6.2009,  13:00 Найти цитируемый пост)
но при этом все равно остается фулскан...

4)Ты уверен в том что фуллскан МЕНЕЕ эффективен?
Случается, порой, я ПРИНУЖДАЮ ораклю использовать full scan, потому как дождаться результата при использовании индексного доступа - терпения не хватает. Ты упоминал ранее что селективность твоего запроса 18%. Это достаточно высокая селективность. На такой селективности я вполне могу поверить что фуллскан будет эффективнее. Все зависит от отношения стоимости операций ввода вывода к стоимости операций CPU. Может так статься что сотни многоблочных чтений с полной загрузкой ЦПУ будут выполняться много быстрее тысяч одноблочных чтений при низкой загурзке ЦПУ.

если ответы на вопросы 1,2,3,4 утвердительные, используй хинт INDEX, как это делает v2v в своем примере.


Это сообщение отредактировал(а) Zloxa - 23.6.2009, 14:35


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Oracle"
Zloxa
LSD

Данный раздел предназначен для обсуждения проблем с Oracle Database, другие продукты Oracle здесь не обсуждаются. Просьба при создании темы, придерживаться следующих правил:

  • при создании темы давайте ей осмысленное название, описывающее суть проблемы
  • указывайте используемую версию базы, способ соединения и язык программирования
  • при ошибках обязательно приводите код ошибки и сообщение сервера
  • приводите код в котором возникла ошибка, по возможности дайте тестовый пример демонстрирующий ошибку
  • при вставке кода используйте соответсвующие теги: [code=sql] [/code] для подсветки SQL и PL/SQL кода, [code=java] [/code] - для Java, и т.д.

  • документация по Oracle: 9i, 10g, 11g
  • книги по Oracle можно поискать здесь
  • действия модераторов можно обсудить здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, LSD.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Oracle | Следующая тема »


 




[ Время генерации скрипта: 0.0583 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.