powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Попытки управления порядком джойнов
14 сообщений из 14, страница 1 из 1
Попытки управления порядком джойнов
    #40025459
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть у меня две большие таблицы, с индексами все в порядке, поэтому внутренний джойн испоняется быстро и эффективно.

Собирался полистать все страницы всех книжек Лема, но оказалось что некоторые страницы склеились:

Код: plsql
1.
2.
3.
4.
select p.text
  from BOOKS b
  join PAGES p on b.id=p.id
 where upper(b.author) like 'LEM, STANISLA%'



ТЕХТ
----
page1
page2
page3,page4,page6
page5
...

Не беда, есть много способов разбить строку, сделал так:
Код: plsql
1.
2.
3.
4.
5.
select column_value
  from BOOKS b
  join PAGES p on b.id=p.id
  cross join TABLE(SplitString(p.text,','))
 where upper(b.author) like 'LEM, STANISLA%'



И тут Оракл хорошо завис (таблицы большие).

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

Код: plsql
1.
2.
3.
4.
select column_value
  from BOOKS b
  join PAGES p on b.id=p.id and upper(b.author) like 'LEM, STANISLA%'
  cross join TABLE(SplitString(p.text,','))



Почему-то думал что это намекнет Ораклу сделать быстрый джойн и фильтр, а уж потом добавить медленный джойн. Nope.
Предикат что в джойне, что в where - одно и то же.

Силой запихал скобками фильтр поглубже - все равно зависает. (таблицы не только длинные, а еще наполовину удаленные)

Код: plsql
1.
2.
3.
4.
5.
select column_value
  from (select text from BOOKS b
           join PAGES p on b.id=p.id 
         where upper(b.author) like 'LEM, STANISLA%')
  cross join TABLE(SplitString(text,','))



Руками отделил быстрое от медленного:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
lems as (
  select p.text 
    from BOOKS b 
    join PAGES p on b.id=p.id 
   where upper(b.author) like 'LEM, STANISLA%'
)
select column_value 
  from lems
  cross join TABLE(SplitString(text,','))



Пришлось смотреть планы, они оказались одинаковые, т.е. Оракл над моими попытками "оптимизировать" тихо посмеялся.

Думаю, как такой запрос ускорить.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025461
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Думаю, как такой запрос ускорить.

Никак. Всё упёрлось в split.

Просто надо сделать, чтобы в pages хранились действительно pages, а не когда pages, а когда comma-separaded хз что. В столбце должны хранится значения одного типа, а не помойка.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025491
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL,

А собственно планы где?
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025594
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Есть у меня две большие таблицы

А поточнее можно? Попробовал сымитировать - таблица книг 1E5 строк, книги "Лема" - каждая 73-я, таблица страниц - 3E7 строк, примерно по 300 "страниц" на книгу. Запятые ставились рандомно от 2 до 10 на строку.
Первичный ключ на "книгах", индекс и фк на него в "страницах".

Парсинг comma-separated строки делал через xmltable + ora:tokenize, общее количество итоговых страниц считается быстро.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025701
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответы, я не писал про мои попытки с токенизацией через XML и regexp/level, чтобы не запутывать тему.

В планах ничего необычного. За всю ночь джойн не отработал.

Коллега ответил, что удаленная, бОльшая часть моих таблиц намного медленней чем местный доступ, поэтому сначала скопирую в местную таблицу.

Суть моего тест-запроса выглядела так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with acu as ( -- (id,title)
  select * from BOOKS_V union -- remove duplicates
  select * from BOOKS_V@dblink_..
),
aca as (       -- (id,text)
  select * from PAGES_V union -- remove duplicates
  select * from PAGES_V@dblink_..
)
select distinct title, column_value 
  from (select * from aca join acu on aca.id = acu.id where acu.id = 30129)
  cross join TABLE(SplitString( text, ',' ))
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025706
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL,

Дайте-ка угадаю, первый пример был не на полном фетче, а на выдаче первых строк?

И опускать "незначительные мелочи" вроде того, что у вас там вьюхи да ещё и по линку - как минимум нелепо, если ожидаете реальной помощи. Угадывать, что издаёт стук в вашем подвале, становится гиблым делом.

з.ы. Ещё немного поугадываю, без прибивания гвоздями в виде вызова функции, исходный план скорее всего выполнялся на удалённом сервере с пробросом туда "маленькой" "местной" части.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025745
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env
НеофитSQL,

Дайте-ка угадаю, первый пример был не на полном фетче, а на выдаче первых строк?

И опускать "незначительные мелочи" вроде того, что у вас там вьюхи да ещё и по линку - как минимум нелепо, если ожидаете реальной помощи. Угадывать, что издаёт стук в вашем подвале, становится гиблым делом.

з.ы. Ещё немного поугадываю, без прибивания гвоздями в виде вызова функции, исходный план скорее всего выполнялся на удалённом сервере с пробросом туда "маленькой" "местной" части.


Первое не угадали.

Второе сейчас посмотрю.. тоже не угадали.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025769
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ошибка была в моем кустарном SplitString(), который не справился с null в 100500 строке и ушел в бесконечный цикл.
После исправления все работает, и dblink не такой уж медленный.

Урок: расслабился с SQL, проверять параметры надо всегда, а не только в боевом коде.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
  function SplitString( str varchar2, div char ) return T_VARCHAR_TABLE pipelined deterministic is
  n integer := 1;
  m integer;
  begin
    loop
      m := instr( str, div, n );
      exit when nvl(m,0) < n; -- было без nvl()
      pipe row( substr(str, n, m-n ) );
      n := m +1;
    end loop;
      pipe row( substr(str, n) );
  end SplitString;
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025843
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
и dblink не такой уж медленный.

Он глючный и имеет свойство рандомно отваливаться. Наши парни, которые за ДБА его не любят.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40025861
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Ошибка была в моем кустарном SplitString()

Ожидаемо.

Предположения по планам и фетчу были высказаны, исходя из предыдущих претензий ТС на высокое качество его процедурного кода. Вот тут точно не угадал.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40026099
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
crutchmaster
НеофитSQL
и dblink не такой уж медленный.

Он глючный и имеет свойство рандомно отваливаться. Наши парни, которые за ДБА его не любят.


Спасибо. Если этот одноразовый отчет попросят сделать по кнопке (или другая похожая задача вовлекающая удаленную* архивную базу), я потестирую скорость/надежность и в случае проблем, закеширую нужные мне таблицы через MV с индексами.

(*)удаленная условно, это другая схема на том же сервере. Возможно, она не подвержена отваливаниям из-за этого.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40026143
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не должно быть новостью для экспертов, но мой запрос перемешивающий дальние/ближние данные не был эффективным, и отрабатывал секунд за 10.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with acu as ( -- (id,title)
  select * from BOOKS_V union -- remove duplicates
  select * from BOOKS_V@dblink_..
),
aca as (       -- (id,text)
  select * from PAGES_V union -- remove duplicates
  select * from PAGES_V@dblink_..
)
select distinct title, column_value 
  from (select * from aca join acu on aca.id = acu.id where acu.id = 30129)
  cross join TABLE(SplitString( text, ',' ))



Как только отделил мух от котлет, все стало летать в разы быстрее:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
with acu as ( -- (id,title)
  select * from BOOKS_V where id = :book_id
union
  select * from BOOKS_V@dblink_..  where id = :book_id
),
aca as (       -- (id,text)
  select * from PAGES_V p
     join acu on p.id = acu.id
union 
  select * from PAGES_V@dblink_..
     join acu on p.id = acu.id
)
select distinct title, column_value 
  from from aca
  cross join TABLE(SplitString( text, ',' ))



Часть, которая прибавила больше всего скорости, отмечена желтым.
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40026146
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вам точно нужен UNION ALL ?
...
Рейтинг: 0 / 0
Попытки управления порядком джойнов
    #40026148
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andreymx
вам точно нужен UNION ALL ?


Намеренно.

Нет уверенности что архивная база не перехлестывается с текущей, поэтому исключаю дубликаты в источниках.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Попытки управления порядком джойнов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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