powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Скорость запроса (PLAN JOIN NATURAL)
19 сообщений из 19, страница 1 из 1
Скорость запроса (PLAN JOIN NATURAL)
    #38936055
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день, помогите ускорить запрос.

Не могу понять почему Firebird (2.5.3) использует NATURAL.
Есть база с таблицами:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE tovar_name (
    num tnum NOT NULL /* TNUM = INTEGER */,
.....
ALTER TABLE tovar_name ADD PRIMARY KEY (num); -- rdb$primary11

CREATE TABLE tovar_zal (
    num tnum NOT NULL /* TNUM = INTEGER */,
.....
ALTER TABLE tovar_zal ADD PRIMARY KEY (num);
CREATE INDEX idx_tovar_zal_tovar_id ON tovar_zal (tovar_id);



в таблице tovar_name 88000 записей
в таблице tovar_zal 70000 записей

Делаю запрос без сортировки :

Код: sql
1.
2.
3.
4.
5.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num = tz.tovar_id)



результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN JOIN (TZ NATURAL, T INDEX (RDB$PRIMARY11))

Adapted Plan
PLAN JOIN (TZ NATURAL, T INDEX (INTEG_26))

------ Performance info ------
Prepare time = 0ms
Execute time = 0ms
Avg fetch time = 0,00 ms
Current memory = 9 605 788
Max memory = 9 658 020
Memory buffers = 2 048
Reads from disk to cache = 2
Writes from cache to disk = 0
Fetches from cache = 241

результат FETCH ALL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN JOIN (TZ NATURAL, T INDEX (RDB$PRIMARY11))

Adapted Plan
PLAN JOIN (TZ NATURAL, T INDEX (INTEG_26))

------ Performance info ------
Prepare time = 0ms
Execute time = 2s 656ms
Avg fetch time = 0,04 ms
Current memory = 9 605 788
Max memory = 9 658 020
Memory buffers = 2 048
Reads from disk to cache = 8 229
Writes from cache to disk = 0
Fetches from cache = 552 963

Делаю запрос с сортировкой по полю с индексом :

Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num = tz.tovar_id)
ORDER BY
  t.num



результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (RDB$PRIMARY11)))

Adapted Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (INTEG_26)))

------ Performance info ------
Prepare time = 0ms
Execute time = 5s 94ms
Avg fetch time = 188,67 ms
Current memory = 70 427 488
Max memory = 70 478 600
Memory buffers = 2 048
Reads from disk to cache = 8 231
Writes from cache to disk = 0
Fetches from cache = 552 963

результат FETCH ALL:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (RDB$PRIMARY11)))

Adapted Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (INTEG_26)))

------ Performance info ------
Prepare time = 0ms
Execute time = 6s 391ms
Avg fetch time = 0,09 ms
Current memory = 9 607 592
Max memory = 70 478 600
Memory buffers = 2 048
Reads from disk to cache = 8 231
Writes from cache to disk = 0
Fetches from cache = 552 963

Делаю запрос с сортировкой по полю с индексом с явным указанием PLAN :

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num = tz.tovar_id)
  PLAN JOIN (t INDEX (rdb$primary11), tz INDEX (idx_tovar_zal_tovar_id))
ORDER BY
  t.num



результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN JOIN (T ORDER RDB$PRIMARY11, TZ INDEX (IDX_TOVAR_ZAL_TOVAR_ID))

Adapted Plan
PLAN JOIN (T ORDER INTEG_26, TZ INDEX (IDX_TOVAR_ZAL_TOVAR_ID))

------ Performance info ------
Prepare time = 0ms
Execute time = 0ms
Avg fetch time = 0,00 ms
Current memory = 9 608 744
Max memory = 70 478 600
Memory buffers = 2 048
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 285

результат FETCH ALL:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN JOIN (T ORDER RDB$PRIMARY11, TZ INDEX (IDX_TOVAR_ZAL_TOVAR_ID))

Adapted Plan
PLAN JOIN (T ORDER INTEG_26, TZ INDEX (IDX_TOVAR_ZAL_TOVAR_ID))

------ Performance info ------
Prepare time = 0ms
Execute time = 2s 812ms
Avg fetch time = 0,04 ms
Current memory = 9 729 548
Max memory = 70 478 600
Memory buffers = 2 048
Reads from disk to cache = 9 123
Writes from cache to disk = 0
Fetches from cache = 746 156

Понятно что запросы гораздо больше и поля чуть не те, все сократил чтобы было максимально понятно. Почему не используется верный индекс при JOIN двух таблиц, а NATURAL? Ведь индекс есть, почему проход по нему не делать, явно ведь быстрее. Я понимаю есть SORT BY, значит он должен склеить две таблицы полностью и потом выдать результат, даже FIRST не поможет. Но индекс же есть почему не клеить по нему? Вот и получается что, ни частичный фетч, ни добавление индекса не помогают пользователю у которого до 100 тыс наименований и хочет сортировать например по других полях, так бы добавил индекс и все, а так склейка происходит по NATURAL и это у пользователя на компе примерно 6-8 секунд :(

В нете смотрел, пример как тут, но так и не понял почему используется NATURAL
http://www.sql.ru/forum/389044/inner-join-dvuh-tablic-daet-plan-natural
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936068
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.ua,

не там смотришь надо здесь http://www.ibase.ru/devinfo/dataaccesspaths.htm

По сабжу. До трёшки Fb не умеет менять порядок соединения когда одна из таблиц читается навигацией по индексу. Смотри CORE-1482
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936075
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у всех запросов планы нормальные.

dimmon.ua Почему не используется верный индекс при JOIN двух таблиц, а NATURAL?
потому что чтобы объединить два множества, элементы одного множества придется перебрать целиком. А соответствия им - да, ищутся по индексу.

У тебя еще там мало данных, но и так видно, что reads from disk to cache у твоего плана с ORDER больше чем у SORT (9123 против 8231). И если данных будет больше, то и запрос с планом ORDER будет гораздо тормознее на FetchAll.

кстати, у тебя нет индекса по tovar_zal.num, а он должен быть, хотя бы в результате построенного по этому стольбцу foreign key.
Тогда план поменяется.
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936077
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.ua,

кстати раз у тебя ORDER выигрывает у SORT при полном фетче, то скорее всего память под сортировку мало выделено. Попробуй параметр TempCacheLimit увеличить раз в 10.
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936081
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисне умеет менять порядок соединения когда одна из таблиц читается навигацией по индексу.
нет. там про SORT vs ORDER. Это массовое заблуждение об однозначной выгоде ORDER, которое я подробно разбирал здесь:
http://www.ibaseforum.ru/viewtopic.php?f=4&t=4175
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936092
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvу тебя нет индекса по tovar_zal.num
упс, не туда посмотрел.
вместо индекса idx_tovar_zal_tovar_id нужно было просто создать foregin key.

и, на будущее, dimmon.ua - не создавай неименованные constraints. Это неудобно при просмотре планов и поиске этих самых constraints.

то есть, надо было писать
ALTER TABLE tovar_name ADD constraint pk_tovar_name PRIMARY KEY (num)

и, в первом запросе одна из таблиц все равно была бы natural. Поскольку в tovar_zal записей меньше, оптимизатор выбрал ее для натурального перебора.
Еще раз повторяю, что это совершенно нормально, так производится объединение множеств. Если бы на tovar_zal было бы дополнительное условие отбора, и был индекс по такому полю, то индекс бы использовался и natural не было бы.
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936110
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv,

ага я перепутал мальца. В том тикете был решён вопрос когда FIRST присутствует. Автору надо память под сортировку увеличить. Глядишь и выгода от ORDER улетучится
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936134
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисГлядишь и выгода от ORDER улетучится
выгода от ORDER есть только когда надо быстро получить первую порцию записей, или когда записей мало. Если записей много, то при FetchAll будет дикий дисковый I/O, и в итоге все окажется хуже SORT

у автора же якобы выгода получилась на
select ...
where field = x
order by field

То есть когда индекс по field используется и для отбора, и для "вывода в указанном порядке". Со слов Еманова (вчера), эту фишка была в 1.5, в 2.x ее поломали, чинят в 3.0, и якобы до сих пор в 2.1 и 2.5 оно работает криво. Детали будут потом, и в т.ч. на упомянутых уже семинарах 17512349
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936173
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Каюсь, неименованные "constraints" как и "foregin key" это наследие, переделал tovar_zal на:

Код: sql
1.
2.
3.
4.
ALTER TABLE 
  tovar_zal 
ADD CONSTRAINT 
  fk_tovar_zal_tovar_id FOREIGN KEY (tovar_id) REFERENCES tovar_name (num) 



Результат такой же, работает только с явным указаниме плана:
Код: sql
1.
PLAN JOIN (t INDEX (rdb$primary11), tz INDEX (fk_tovar_zal_tovar_id))



Мне не нужен Fetch All, я его для примера показал, мне бы обычный Fetch части данных бы срабатывал быстро, но пока используется NATURAL в плане, ничего не выходит, склейка так и идет по NATURAL :(

Честно, вот читаю уже который раз и не могу понять:
авторЕще раз повторяю, что это совершенно нормально, так производится объединение множеств. Если бы на tovar_zal было бы дополнительное условие отбора, и был индекс по такому полю, то индекс бы использовался и natural не было бы.
индекс есть, а зачем доп. условие отбора? Я и до этого читал, вы также писали ранее, но реально туплю не понимаю, сори.

В ORDER BY же указано поле и по нему есть индекс, почему не идет перебор по нему. Вы не подумайте что этот JOIN я делал только так, и явно и неявно и местами менял tovar_zal и tovar_name и ка хочешь :)

Просто я не понимаю одного, есть две таблицы, есть поле первичного ключа у каждой таблицы, есть поле по которому идет JOIN (внешний ключ), есть поле сортировки. И по каждому из них есть индексы, почему NATURAL?
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936186
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv,

в трёшке выгода есть. Но именно на таком запросе. А не на JOINах.
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936188
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kdvу автора же якобы выгода получилась на
select ...
where field = x
order by field

Суть в том что даже если букс у одного клиента, я просто добавляю индекс по нужному полю для клиента, и вопрос решен, но кроме добавления индекса по полю надо задавать и вручную план. Т.е. добавляю:

Код: sql
1.
CREATE INDEX tovar_name_name ON tovar_name (name)



И при выборке:
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num = tz.tovar_id)
ORDER BY
  t.name



получаю:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (RDB$PRIMARY11)))

Adapted Plan
PLAN SORT (JOIN (TZ NATURAL, T INDEX (INTEG_26)))

------ Performance info ------
 Prepare time = 0ms
Execute time = 5s 438ms 
Avg fetch time = 201,41 ms
Current memory = 70 455 856
Max memory = 85 120 596
Memory buffers = 2 048
Reads from disk to cache = 8 229
Writes from cache to disk = 0
Fetches from cache = 552 925

а вот с явным указанием плана:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num = tz.tovar_id)
  PLAN JOIN (t INDEX (tovar_name_name), tz INDEX (fk_tovar_zal_tovar_id))
ORDER BY
  t.name



результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Plan
PLAN JOIN (T ORDER TOVAR_NAME_NAME, TZ INDEX (FK_TOVAR_ZAL_TOVAR_ID))

------ Performance info ------
 Prepare time = 0ms
Execute time = 0ms 
Avg fetch time = 0,00 ms
Current memory = 9 637 952
Max memory = 85 120 596
Memory buffers = 2 048
Reads from disk to cache = 35
Writes from cache to disk = 0
Fetches from cache = 315
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936190
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.ua,

ну так напиши

Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON t.num+0 = tz.tovar_id
ORDER BY
  t.num



будет тебе сортировка по индексу
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936214
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Елки, а я все искал куда этот "+0" вставить, читал но не мог понять куда :) Спасибо огроменное, это меня очень устраивает на данный момент, скрипт:
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num+0 = tz.tovar_id)
ORDER BY
  t.name



выдает
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Plan
PLAN JOIN (T ORDER TOVAR_NAME_NAME, TZ INDEX (FK_TOVAR_ZAL_TOVAR_ID))

------ Performance info ------
 Prepare time = 0ms
Execute time = 0ms 
Avg fetch time = 0,00 ms
Current memory = 9 637 080
Max memory = 85 120 596
Memory buffers = 2 048
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 307
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936362
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.uaно пока используется NATURAL в плане, ничего не выходит
рискну двинуть в массы лозунг - "NATURALа боятся только гомосеки". Потому что эта беда с "NATURAL - плохо, я его боюсь!" меня уже конкретно достала.
NATURAL - САМЫЙ БЫСТРЫЙ способ перебора всей таблицы.

Сколько раз я должен повторить про объединение множеств? И сколько раз ты будешь задавать один и тот же вопрос?
Ты в уме можешь решить задачу? Есть массив А и массив Б. Нужно для массива А найти соответствующие ему элементы в массиве Б. Как ты это сделаешь? Про индексы не думай, представь просто набор каких-то элементов в памяти.

dimmon.uaВ ORDER BY же указано поле и по нему есть индекс, почему не идет перебор по нему.
потому что.

dimmon.uaнадо задавать и вручную план.
да никогда не надо задавать план вручную.

dimmon.uaа вот с явным указанием плана:
ты ответы читаешь, или только вопросы пишешь? или это какой-то вид троллинга? Тебе уже ЭТО объяснили, здесь. И дали ссылку на статью. При этом ты пятый раз спрашиваешь "почему."
Зачем ты тычешь в Execute time, при этом сам же приводя время выполнения для fetch all?
я для кого писал 17513776 17513464 17513438 ?
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936367
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.ua,

я еще на всякий случай добавлю, что 9000 страниц за 5 секунд - это 14мб/сек. На старом ноутбуке экспериментируешь?
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936487
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kdvСколько раз я должен повторить про объединение множеств? И сколько раз ты будешь задавать один и тот же вопрос?
Ты в уме можешь решить задачу? Есть массив А и массив Б. Нужно для массива А найти соответствующие ему элементы в массиве Б. Как ты это сделаешь? Про индексы не думай, представь просто набор каких-то элементов в памяти.


Пожалуйста.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
 tovar_name 
num name
0  Имя2
1  Имя3
2  Имя6
3  Имя8
4  Имя1
5  Имя9
6  Имя0
7  Имя4
8  Имя5
9  Имя7
 tovar_zal 
num tovar_id
0  5
1  4
2  7
3  9
4  1
5  6
6  2
7  3
8  5

Делаем запрос:
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT
  t.*
FROM
  tovar_name t
    JOIN tovar_zal tz ON (t.num+0 = tz.tovar_id)
ORDER BY
  t.name



Допустим обычный Fetch вытаскивает 4 строки, Fetch All все данные.

Как я понимаю, Firebird возмет таблицу tovar_zal (т.к. она меньше) в NATURAL сортировке т.е. без нее и будет подставлять по индексу поля num таблицы tovar_name, но он не возмет 4 строки, а будет связывавть таблицы полностью т.к. чтобы отсортировыать 4 строки по name нада склеить все, и после дать только 4 строки отсортированные по name не используя индекс. Именно в полной склейке и подальшей сортировкой не по индексу и будет букс. А вот если Firebird возмет таблицу tovar_name сразу по индексу name (что и делаем мы указывая явно План) и потом подклеит 4 записи опять таки по индексу num таблицы tovar_zal, то не надо клеить всю таблицу на что траитится время + сортировка уже есть и она бала сделана по индексу и только 4 записи.

kdvда никогда не надо задавать план вручную.


Поэтому и спрашиваю т.к. не хочу задавать его вручную.

kdvпотому что.


Почему?

kdvЗачем ты тычешь в Execute time, при этом сам же приводя время выполнения для fetch all?


Я не "тычу" я хотел показывал fetch all, только для общей картины, чтобы не задавали лишних вопросов, вроде какая версия, какая статистика, за какое время fetch all, т.е. хотел как лучше :) чтобы вам быфло проще.
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936488
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kdvdimmon.ua,

я еще на всякий случай добавлю, что 9000 страниц за 5 секунд - это 14мб/сек. На старом ноутбуке экспериментируешь?

Эксперимент был на embedded, проц E6700, windows xp, винт обычный
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936517
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimmon.ua,

на embeded тест не чистый. Надо было на нормальной версии проводить. Кстати про увеличение памяти про сортировку ты совет проигнорировал. Впрочем если надо получать быстро только первые записи, то сортировка по индексу в будет в тему
...
Рейтинг: 0 / 0
Скорость запроса (PLAN JOIN NATURAL)
    #38936732
dimmon.ua
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов Денисна embeded тест не чистый. Надо было на нормальной версии проводить. Кстати про увеличение памяти про сортировку ты совет проигнорировал. Впрочем если надо получать быстро только первые записи, то сортировка по индексу в будет в тему

Спасибо с TempCacheLimit вы мне еще в прошлый раз помогли :) 17377270 на эксперименте уже было увеличено.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Скорость запроса (PLAN JOIN NATURAL)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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