powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по "плановому хозяйству"
25 сообщений из 41, страница 1 из 2
Вопрос по "плановому хозяйству"
    #39329055
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день, коллеги! Есть, скажем так, словарик:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE TABLE INDEXER_WORDS (
    WORD_ID  INTEGER NOT NULL,
    WORD     VARCHAR(50)
);
ALTER TABLE INDEXER_WORDS ADD CONSTRAINT PK_INDEXER_WORDS PRIMARY KEY (WORD_ID);
CREATE INDEX INDEXER_WORDS_IDX1 ON INDEXER_WORDS (WORD);

CREATE TABLE INDEXER_FILES (
    ID        INTEGER NOT NULL,
    WORD_ID   INTEGER,
    FILE_ID   INTEGER,
    WORD_NUM  INTEGER
);

ALTER TABLE INDEXER_FILES ADD CONSTRAINT PK_INDEXER_FILES PRIMARY KEY (ID);
ALTER TABLE INDEXER_FILES ADD CONSTRAINT FK_INDEXER_FILES_1 FOREIGN KEY (WORD_ID) REFERENCES INDEXER_WORDS (WORD_ID) ON DELETE CASCADE;



Сервер: х64 2.5.6.27020 Superserver

Выполняю в нем поиск по нескольким словам разными способами:
JOIN
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select distinct
ifl1.file_id
from indexer_files ifl1
join indexer_files ifl2 on ifl2.file_id=ifl1.file_id
join indexer_files ifl3 on ifl3.file_id=ifl1.file_id
join indexer_words iw on ifl1.word_id=iw.word_id
join indexer_words iw2 on ifl2.word_id=iw2.word_id
join indexer_words iw3 on ifl3.word_id=iw3.word_id
where iw.word like 'ивано%'
and iw2.word like 'петр'
and iw3.word like 'михайлович'



План
PLAN SORT (MERGE (SORT (JOIN (IW3 INDEX (INDEXER_WORDS_IDX1), IFL3 INDEX (FK_INDEXER_FILES_1))), SORT (JOIN (IW2 INDEX (INDEXER_WORDS_IDX1), IFL2 INDEX (FK_INDEXER_FILES_1))), SORT (JOIN (IW INDEX (INDEXER_WORDS_IDX1), IFL1 INDEX (FK_INDEXER_FILES_1)))))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 3s 230ms
Среднее время на получение одной записи = 100,94 ms
Current memory = 341 745 248
Max memory = 347 191 168
Memory buffers = 20 480
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 36 079

IR (индексные чтения iw=indexer_words, if=indexer_files)
iw=441
if=17429

EXISTS
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
select distinct
ifl1.file_id
from indexer_files ifl1
join indexer_words iw1 on ifl1.word_id=iw1.word_id
where iw1.word like 'ивано%'
and
exists(select ifl2.word_id
       from indexer_files ifl2
       join indexer_words iw2 on iw2.word_id=ifl2.word_id
       where ifl2.file_id=ifl1.file_id
       and iw2.word like 'петр')
and
exists(select ifl3.word_id
       from indexer_files ifl3
       join indexer_words iw3 on iw3.word_id=ifl3.word_id
       where ifl3.file_id=ifl1.file_id
       and iw3.word like 'михайлович')



План
PLAN JOIN (IW2 INDEX (INDEXER_WORDS_IDX1), IFL2 INDEX (FK_INDEXER_FILES_1))
PLAN JOIN (IW3 INDEX (INDEXER_WORDS_IDX1), IFL3 INDEX (FK_INDEXER_FILES_1))
PLAN SORT (JOIN (IW1 INDEX (INDEXER_WORDS_IDX1), IFL1 INDEX (FK_INDEXER_FILES_1)))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 19s 594ms
Среднее время на получение одной записи = 612,31 ms
Current memory = 341 744 048
Max memory = 347 191 168
Memory buffers = 20 480
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 38 754 241

IR
iw=3 868 801
if=15 455 282

EXECUTE BLOCK
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
EXECUTE BLOCK returns (
file_id INTEGER)
AS
declare variable ex INTEGER;
declare variable ex2 INTEGER;
BEGIN
  FOR select distinct ifl1.file_id
  from indexer_files ifl1
  join indexer_words iw1
  on ifl1.word_id=iw1.word_id
  where iw1.word like 'ивано%'
  INTO :file_id do
  BEGIN
    ex=null;
    ex2=null;

    select first 1 ifl2.word_id
    from indexer_files ifl2
    join indexer_words iw2 on iw2.word_id=ifl2.word_id
    where ifl2.file_id=:file_id
    and iw2.word like 'петр' into :ex;

    if (:ex is not null) then
    begin
      select first 1 ifl3.word_id
      from indexer_files ifl3
      join indexer_words iw3 on iw3.word_id=ifl3.word_id
      where ifl3.file_id=:file_id
      and iw3.word like 'михайлович' into :ex2;
    end

    if ((:ex is not null) and (:ex2 is not null)) then SUSPEND;
  END
END



План
PLAN JOIN (IW2 INDEX (INDEXER_WORDS_IDX1), IFL2 INDEX (FK_INDEXER_FILES_1))
PLAN JOIN (IW3 INDEX (INDEXER_WORDS_IDX1), IFL3 INDEX (FK_INDEXER_FILES_1))
PLAN SORT (JOIN (IW1 INDEX (INDEXER_WORDS_IDX1), IFL1 INDEX (FK_INDEXER_FILES_1)))

------ Информация о производительности ------
Время подготовки запроса = 16ms
Время выполнения запроса = 4s 602ms
Среднее время на получение одной записи = 143,81 ms
Current memory = 341 756 368
Max memory = 347 191 168
Memory buffers = 20 480
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 8 943 775

IR
iw=998 835
if=3 460 451

Вопрос: почему так отличаются планы выполнения и использование ресурсов?
Мне кажется, что exists и execute block технически должны выполняться одинаково. Я где-то ошибаюсь?
Для некоторых запросов execute block ощутимо выигрывает по времени даже у join.
В общем я потерялся....
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329065
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,

с выборками из execute block и процедур не забывай делать fetch all. А то по suspend получил первый блок записей за 4 секунды, и обрадовался.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329071
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv, не не это я конечно учел. Там просто всего 20 записей. Они по-любому фетчатся все.

p.s. в indexer_words около 370 000 записей, а в indexer_files около 24 000 000
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329127
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,

а чего это у тебя file_id не индексирован? Неудивительно что тормоза есть, т.к. соединение использует MERGE JOIN многократно.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329134
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

хотя... не поможет
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329138
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Дениса чего это у тебя file_id не индексирован?дык я тоже подумал:"а чего это он у меня не индексирован". Проиндексировал...и сервер ушел в себя. Не дождался - срубил (остановил службу).
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329139
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57..и сервер ушел в себяВ смысле при выполнении запроса join.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329142
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и file_id уникальных значений около 28 000 из 24 000 000. Не самый лучший индекс наверное.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329262
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57Мне кажется, что exists и execute block технически должны выполняться одинаково. Я где-то ошибаюсь?
Показалось, что таки ошибаюсь и должно быть так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
select file_id
from
(select distinct ifl1.file_id
from indexer_files ifl1
join indexer_words iw1 on ifl1.word_id=iw1.word_id
where iw1.word like 'ивано%') dt
where
exists(select ifl2.word_id
       from indexer_files ifl2
       join indexer_words iw2 on iw2.word_id=ifl2.word_id
       where ifl2.file_id=dt.file_id
       and iw2.word like 'петр')
and
exists(select ifl3.word_id
       from indexer_files ifl3
       join indexer_words iw3 on iw3.word_id=ifl3.word_id
       where ifl3.file_id=dt.file_id
       and iw3.word like 'михайлович')


Но результат еще хуже.
Время: 41 сек.
iw=978 000
if=52 400 000
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329268
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,

exists здесь будет всегда хуже JOIN, т.к. нет индекса. EXISTS не умеет выполняться с помощью HASH OUTER SEMI JOIN.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329271
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисBarmaley57,

exists здесь будет всегда хуже JOIN, т.к. нет индекса. EXISTS не умеет выполняться с помощью HASH OUTER SEMI JOIN.Да, я это понимаю (надеюсь))) Тут вопрос в другом:
авторМне кажется, что exists и execute block технически должны выполняться одинаково
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329275
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и вот это
авторДля некоторых запросов execute block ощутимо выигрывает по времени даже у join
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329280
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57Тут вопрос в другом:
авторМне кажется, что exists и execute block технически должны выполняться одинаково

не совсем. distinct делается уже после exists, а в execute block до.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329282
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисBarmaley57Тут вопрос в другом:
пропущено...


не совсем. distinct делается уже после exists, а в execute block до.Дык а здесь 19796420 тоже что-ли после?
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329333
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,

ради интереса проверь вот этот запрос

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
WITH t1
AS (SELECT DISTINCT
        ifl.file_id
    FROM
        indexer_files ifl
        JOIN indexer_words iw ON ifl.word_id = iw.word_id
    WHERE
          iw.word LIKE 'ивано%'),
t2
AS (SELECT DISTINCT
        ifl.file_id
    FROM
        indexer_files ifl
        JOIN indexer_words iw ON ifl.word_id = iw.word_id
    WHERE
          iw.word LIKE 'петр'),
t3
AS (SELECT DISTINCT
        ifl.file_id
    FROM
        indexer_files ifl
        JOIN indexer_words iw ON ifl.word_id = iw.word_id
    WHERE
          iw.word LIKE 'михайлович')
SELECT
    t1.file_id
FROM
    t1
    JOIN t2 ON t2.file_id = t1.file_id
    JOIN t3 ON t3.file_id = t1.file_id
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329708
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис, попробовал. Результат очень хороший:
результатPLAN MERGE (SORT (SORT (JOIN (T4 IW INDEX (INDEXER_WORDS_IDX1), T4 IFL INDEX (FK_INDEXER_FILES_1)))), SORT (SORT (JOIN (T3 IW INDEX (INDEXER_WORDS_IDX1), T3 IFL INDEX (FK_INDEXER_FILES_1)))), SORT (SORT (JOIN (T2 IW INDEX (INDEXER_WORDS_IDX1), T2 IFL INDEX (FK_INDEXER_FILES_1)))), SORT (SORT (JOIN (T1 IW INDEX (INDEXER_WORDS_IDX1), T1 IFL INDEX (FK_INDEXER_FILES_1)))))

время ~200 мсек. Чтения такие же, как при join.

Никогда не приходилось использовать синтаксис WITH [RECURSIVE]. Уже думал в эту сторону, но ты меня опередил.

Спасибо за подсказку.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329745
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57,

запрос с CTE точно такой же, как и первый с JOIN.
Разве что его приятнее читать :)
Вот только в плане ты показал 4 таблицы, а не 3...
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329746
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladзапрос с CTE точно такой же, как и первый с JOIN.Не, соврал немного - с CTE дистинкты в каждом выражении есть. Но суть - та же
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329764
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad,

я исходил из предположения, что с помощью дистинктов в каждом CTE уменьшу мощность множеств для соединения алгоритмом MERGE JOIN. Видимо не ошибся :)
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329911
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

В 3.0 ещё и HASH JOIN можно подключить, может ускорится.

Не совсем кейс ТС, но иногда такие штуки через группировку можно быстро собрать.

Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE WORDS (
    WORD     VARCHAR(128),
    HASH_ID  INTEGER
);

CREATE INDEX WORDS_IDX1 ON WORDS COMPUTED BY (UPPER(WORD));



Записей ~800'000 всего, и 1109 во всех результатах

В лоб
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select distinct w1.hash_id from WORDS w1
 inner join WORDS w2 on w1.hash_id = w2.hash_id
 inner join WORDS w3 on w3.hash_id = w2.hash_id
 where
  UPPER(w1.word) like 'SELECT'
 and UPPER(w2.word) like 'BEGIN'
  and UPPER(w3.word) like 'GROUP'
-- Execute time = 593ms
-- WORDS Indexed reads 8323


через group by
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select w.hash_id, count(distinct UPPER(w.word)) from words w
where UPPER(w.word) like 'SELECT'
 or UPPER(w.word) like 'BEGIN'
  or UPPER(w.word) like 'GROUP'
group by 1
having count(distinct UPPER(w.word)) = 3
-- Execute time = 125ms
-- WORDS Indexed read 9103


через hash join (FB3.0)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select distinct w1.hash_id from WORDS w1
 inner join WORDS w2 on w1.hash_id+0 = w2.hash_id+0
 inner join WORDS w3 on w3.hash_id+0 = w2.hash_id+0
 where
  UPPER(w1.word) like 'SELECT'
 and UPPER(w2.word) like 'BEGIN'
  and UPPER(w3.word) like 'GROUP'
-- Execute time = 47ms
-- WORDS Indexed read 9103
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329923
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgmВ 3.0 ещё и HASH JOIN можно подключить, может ускорится.

Пока что в 3.0 HASH JOIN работает вместо MERGE JOIN. Никакого выбора по стоимости нет, да и заставить соединять MERGEм тройку нельзя. В теории MERGE может быть быстрее HASH если множества и так отсортированы по соединяемым полям, и если исключить двойную сортировку.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329943
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladBarmaley57,
запрос с CTE точно такой же, как и первый с JOIN.
Разве что его приятнее читать :)
Вот только в плане ты показал 4 таблицы, а не 3...По скорости выполнения получается, что не такой же. План я не тот привел. Каюсь. Просто сразу еще попробовал на 4-х соединениях.
Симонов Денис я исходил из предположения, что с помощью дистинктов в каждом CTE уменьшу мощность множествя вот как раз тоже самое хотел сделать, только не вкуривал как
afgmтакие штуки через группировку можно быстро собрать.это у меня был первоначальный вариант. Работал и правда очень шустро, но потом пришлось от него отказаться из-за доп.условий поиска.

Отцы, спасибо всем за участие. С вами приятно иметь дело)
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39329951
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисПока что в 3.0 HASH JOIN работает вместо MERGE JOIN. Никакого выбора по стоимости нет, да и заставить соединять MERGEм тройку нельзя.

Это порой печалит, согласен. Hash join пока в начале своего внедрения в FB, и для left join тоже появится, надеюсь. Я вот ещё не нашёл почему в FB нет merge LEFT join...
Симонов ДенисВ теории MERGE может быть быстрее HASH если множества и так отсортированы по соединяемым полям, и если исключить двойную сортировку.
Тут всё не так однозначно.
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39331512
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дабы не создавать ненужной темы, спрошу здесь: правильно я понимаю, что остановить долгоиграющий запрос кроме как черезжопным методом с помощью генератора или путем удаления записи из MON$ нельзя?
...
Рейтинг: 0 / 0
Вопрос по "плановому хозяйству"
    #39331517
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
на классике ещё можешь процесс кильнуть
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
25 сообщений из 41, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по "плановому хозяйству"
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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