powered by simpleCommunicator - 2.0.44     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Join по неизвестным таблицам
8 сообщений из 8, страница 1 из 1
Join по неизвестным таблицам
    #32064355
Фотография Eter Panji
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такая задача:
разработчики софта обратились ко мне с вопросом
1) есть необходимость делать объединения по нескольким таблицам
2) сама структура каждой из таблиц заранее неизвестна
3) у каждой таблицы есть первичный ключ ROW16
4) объединения идут по первичному ключу
5) FK между таблицами обеспечивается на уровне Application Server. Разработчики гарантируют что сбоев в работе FK не будет.
7) размер таблиц до нескольких сот тысяч строк
8) обновления данных редкие
9) запросы надо создавать динамически (программно)
Вот пример такого запроса
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from 
(SELECT 
main.id, main.name1, a_id, b_id, c_id, dict_a.name1 as a_name1, dict_b.name1 as b_name1, dict_c.name1 as c_name1 
FROM main, dict_a, dict_b, dict_c 
WHERE main.a_id = dict_a.id and main.b_id = dict_b.id and main.c_id = dict_c.id AND ( main.id > '0000000000000000') 
ORDER BY name1,  main.id ) 
WHERE rownum <=  40 

Время обработки такого запроса ужасающе - более минуты

Нужно минимизировать время исполнения.

________________________________________
Я предложил
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select * from 
(SELECT 
  main.id, main.name1, a_id, b_id, c_id, dict_a.name1 as a_name1, dict_b.name1 as b_name1, dict_c.name1 as c_name1 
  FROM 
   (Select * from
     (Select id, name1, a_id, b_id, c_id from main
       Where main.id > '0000000000000000' 
       ORDER BY name1, id
     ) WHERE rownum <=  40 
   )
    main, dict_a, dict_b, dict_c 
  WHERE main.a_id = dict_a.id and main.b_id = dict_b.id and main.c_id = dict_c.id 
)


И увеличить Sort_aria_size

____________________________________
Мне кажется что это не единственное и не наилучшее решение. Однако ничего другого универсального я предложить не могу.

Кстати мне показалось интересным что ни в первом ни во втором случае план исполнения не показывает обращения к индексам таблицы MAIN. Почему?

Еще интересно что увеличением sort_aria_size я добился ускорения в несколько раз и всё. Дальнейшее увеличение ни к чему не ведет, хотя оперативная память еще есть.

К вышесказанному сильно используется Temproary tablespace. Неужели нельзя добиться чтобы для исполнения запроса не требовалось до 200M во временном пространстве.

Еще замечание хинт FirstRows замедляет выполнение запроса по сравнению с AllRows. Незначительно но замедляет. Почему если нужно всего 40 строк из 100000 хинт так работает.

Буду благодарен за любые высказывания.
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32064741
.dba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я, наверное, что-то посоветовал бы :-), если бы увидел план выполнения и иниц. параметры, влияющие на оптимизатор. А как там со сбором статистики?
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32064971
Фотография Eter Panji
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Запрос выглядит так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select * from 
(SELECT 
  main.id, main.name1, a_id, b_id, c_id, dict_a.name1 as a_name1, dict_b.name1 as b_name1, dict_c.name1 as c_name1 
  FROM 
   (Select   /*+INDEX_DESC(main IDX_MAIN_NAME)*/  * from
     (Select id, name1, a_id, b_id, c_id from main
       Where main.id > '0000000000000000' 
       ORDER BY name1, id
     ) WHERE rownum <=  40 
   )
    main, dict_a, dict_b, dict_c 
  WHERE main.a_id = dict_a.id and main.b_id = dict_b.id and main.c_id = dict_c.id 
)


PL/SQL DEVELOPER показывает так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
SELECT STATEMENT, GOAL = CHOOSE			 2708 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 2465000 
 NESTED LOOPS			 2708 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 2465000 
  NESTED LOOPS			 2658 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 1880000 
   HASH JOIN			 2608 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 1295000 
    VIEW	STAS		 2565 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 710000 
     COUNT STOPKEY					 05 . 11 . 2002   14 : 20 : 57 	
      VIEW	STAS		 2565 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 710000 
       SORT ORDER BY STOPKEY			 2565 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 1340000 
        TABLE ACCESS FULL	STAS	MAIN	 2360 	 5000 	 05 . 11 . 2002   14 : 20 : 57 	 1340000 
    INDEX FULL SCAN	STAS	IX_DICT_A	 26 	 10000 	 05 . 11 . 2002   14 : 20 : 57 	 1170000 
   TABLE ACCESS BY INDEX ROWID	STAS	DICT_B	 1 	 10000 	 05 . 11 . 2002   14 : 20 : 57 	 1170000 
    INDEX UNIQUE SCAN	STAS	PK_DICT_B		 10000 	 05 . 11 . 2002   14 : 20 : 57 	
  TABLE ACCESS BY INDEX ROWID	STAS	DICT_C	 1 	 10000 	 05 . 11 . 2002   14 : 20 : 57 	 1170000 
   INDEX UNIQUE SCAN	STAS	PK_DICT_C		 10000 	 05 . 11 . 2002   14 : 20 : 57 	

хотя на самом деле выигрыш по времени от хинта есть.

Параметры

optimizer_index_cost_adj = 1
sort_area_size увеличен c 65 до 1000 Кб
optimizer_mode - разное лучше всего под CHOOSE или ALL_ROWS
hash_area_size - не задано
optimizer_features_enable при задании в TRUE не стартует экземпляр
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32064974
Фотография Eter Panji
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да еще такая заметка разработчики хотят сделать тиражируемый програмный продукт
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32064988
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем же так извращаться?:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 "  FROM 
   (Select  /*+INDEX_DESC(main IDX_MAIN_NAME)*/  * from
     (Select id, name1, a_id, b_id, c_id from main
       Where main.id > '0000000000000000' 
       ORDER BY name1, id
     ) WHERE rownum <=  40 
   "


Если ты используешь INDEX_DESC -тебе нет необходимости делать select из select-а. И еще, тебя никто что-ли не научил, что можно использовать алиасы, вместо названий таблиц? И что за идиотское main.id > '0000000000000000'?
Для чего это? Для того что-бы задействовать индекс?
Судя по плану выполнения он у тебя вообще не задействован. Не проще ли вот так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SELECT
  m.id, m.name1, a_id, 
  b_id, c_id, a.name1, 
  b.name1, c.name1 
 FROM 
   (SELECT  /*+ INDEX_DESC(main idx_main_name) */   
      id, name1, a_id, b_id, c_id 
     FROM main
     WHERE id is not null and rownum <=  40 
     ORDER BY name1, id
   ) m, 
   dict_a a, 
   dict_b b, 
   dict_c c
  WHERE 
    m.a_id = a.id and 
    m.b_id = b.id and 
    m.c_id = c.id


Попробуй это. И план сообщи какой.
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32064998
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще, сортировка вообще говоря в м - тоже не имеет смысла. Если тебе нужно в результирующем запросе получить сортировку, значит надо на его уровне это делать:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT
  m.id, m.name1, a_id, 
  b_id, c_id, a.name1, 
  b.name1, c.name1 
 FROM 
   (SELECT  /*+ INDEX_DESC(main idx_main_name) */   
      id, name1, a_id, b_id, c_id 
     FROM main
     WHERE id is not null and rownum <=  40 
   ) m, 
   dict_a a, 
   dict_b b, 
   dict_c c
  WHERE 
    m.a_id = a.id and 
    m.b_id = b.id and 
    m.c_id = c.id
 ORDER BY 
   m.name1, m.id
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32065086
Фотография Eter Panji
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На счет алиасов:
у них запросы генерятся программно им так удобней,
а на производительности это никак не сказывается

На счет:
"Main.ID>" это опять таки и для чего-то нужно и жить они без этого не могут.

Сортировка не нужна, нужно чтобы выбрались именно первые записи.

А вот то что убралось ORDER BY это здорово. Всё залетало
так как я во сне не представлял
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
SELECT
  m.id, m.name1, a_id, 
  b_id, c_id, a.name1, 
  b.name1, c.name1 
 FROM 
   (SELECT  /*+ INDEX_ASC(main idx_main_name) */   
      id, name1, a_id, b_id, c_id 
     FROM main
     WHERE id>'0000000000000000'  and rownum <=  40 
   ) m, 
   dict_a a, 
   dict_b b, 
   dict_c c
  WHERE 
    m.a_id = a.id and 
    m.b_id = b.id and 
    m.c_id = c.id 
  order by m.id


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
SELECT STATEMENT, GOAL = CHOOSE			 563 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 2465000 
 SORT ORDER BY			 563 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 2465000 
  NESTED LOOPS			 192 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 2465000 
   NESTED LOOPS			 142 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 1880000 
    HASH JOIN			 92 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 1295000 
     VIEW	STAS		 49 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 710000 
      COUNT STOPKEY					 05 . 11 . 2002   18 : 37 : 35 	
       TABLE ACCESS BY INDEX ROWID	STAS	MAIN	 49 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	 1340000 
        INDEX FULL SCAN	STAS	IDX_MAIN_NAME	 3226 	 5000 	 05 . 11 . 2002   18 : 37 : 35 	
     INDEX FULL SCAN	STAS	IX_DICT_A	 26 	 10000 	 05 . 11 . 2002   18 : 37 : 35 	 1170000 
    TABLE ACCESS BY INDEX ROWID	STAS	DICT_B	 1 	 10000 	 05 . 11 . 2002   18 : 37 : 35 	 1170000 
     INDEX UNIQUE SCAN	STAS	PK_DICT_B		 10000 	 05 . 11 . 2002   18 : 37 : 35 	
   TABLE ACCESS BY INDEX ROWID	STAS	DICT_C	 1 	 10000 	 05 . 11 . 2002   18 : 37 : 35 	 1170000 
    INDEX UNIQUE SCAN	STAS	PK_DICT_C		 10000 	 05 . 11 . 2002   18 : 37 : 35 	
...
Рейтинг: 0 / 0
Join по неизвестным таблицам
    #32065180
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну что-ж я рад. Но дело тут не в ORDER BY(или не только в этом). Посмотри план и сравни его со старым. Вместо FULL SCAN по main, теперь идёт TABLE ACCESS BY INDEX ROWID. Это главное.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Join по неизвестным таблицам
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]