SQLRU.net
Разработка приложений баз данных

Начало » Использование СУБД » Firebird, HQbird, InterBase » Ненужные сканы записей при rows
Ненужные сканы записей при rows [сообщение #5911] Fri, 21 February 2025 12:49 Переход к следующему сообщению
marcodor в настоящее время в онлайне  marcodor
Сообщений: 6
Зарегистрирован: June 2022
Junior Member
Добрый день,

Имеем такой запрос:

select
  b.id, b.fdate,
  c.code, c.name
from ta_bundle b
left join ta_entity c on (c.id = b.entity_id)
rows 1000 to 1010

План выполнения:

Select Expression
    -> First N Records
        -> Skip N Records
            -> Nested Loop Join (outer)
                -> Table "TA_BUNDLE" as "B" Full Scan
                -> Filter
                    -> Table "TA_ENTITY" as "C" Access By ID
                        -> Bitmap
                            -> Index "PK_TA_ENTITY" Unique Scan

Сканы записей из таблиц:

TA_BUNDLE - 1010
TA_ENTITY - 1010

Хочется чтобы при больших таблицах и скипов движок читал только нужные 10 записей из TA_ENTITY, а не все 1010.


Через lateral то же самое получается:

select
  b.id, b.fdate,
  c.code, c.name
from ta_bundle b
left join lateral (
  select c.code, c.name
  from ta_entity c
  where c.id = b.entity_id) c on true
rows 1000 to 1010

Работает хорошо только когда подзапрос:

select
  b.id, b.fdate,
  -- ? c.code
  (select c.name from ta_entity c where c.id = b.entity_id)
from ta_bundle b
rows 1000 to 1010

Но так больше одного поля не вытянуть из другой таблицы.
Можно как-то по другому сформировать запрос чтобы движок оптимально сканировал записи?
Тестирую с FB 5.0.1
Re: Ненужные сканы записей при rows [сообщение #5912 является ответом на сообщение #5911] Fri, 21 February 2025 14:27 Переход к предыдущему сообщениюПереход к следующему сообщению
marcodor в настоящее время в онлайне  marcodor
Сообщений: 6
Зарегистрирован: June 2022
Junior Member
Хм.. вот так читает оптимально:

with b as (
  select
    b.id, b.fdate, b.entity_id
  from ta_bundle b
  rows 1000 to 1010
  )
select
  b.id, b.fdate,
  c.code, c.name
from b
left join ta_entity c on (c.id = b.entity_id)
Если по другому никак, то получается генерировать такие монструозные запросы Wink
Re: Ненужные сканы записей при rows [сообщение #5913 является ответом на сообщение #5912] Fri, 21 February 2025 14:38 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время не в онлайне  SD
Сообщений: 430
Зарегистрирован: August 2022
Senior Member
Чисто из любопытства: ты в курсе, что ROWS без ORDER BY - пустая трата времени?..

Нет способа определить какая запись будет 1000-й, не прочитав предыдущие 999.

Поэтому пагинацию надо делать на клиенте.

[Обновления: Fri, 21 February 2025 14:39]

Известить модератора

Re: Ненужные сканы записей при rows [сообщение #5914 является ответом на сообщение #5913] Fri, 21 February 2025 14:52 Переход к предыдущему сообщениюПереход к следующему сообщению
marcodor в настоящее время в онлайне  marcodor
Сообщений: 6
Зарегистрирован: June 2022
Junior Member
Цитата:
ROWS без ORDER BY - пустая трата времени
есть и order by, конечно, пример урезанный, для понимания сути.

Цитата:
Нет способа определить какая запись будет 1000-й, не прочитав предыдущие 999
Естественно, но достаточно читать записи из ta_bundle, без 1000 чтений из ta_entity.
Важно получать нужный срез из главной таблицы, а потом обогащать датасет дополнительной инфы.

Цитата:
Поэтому пагинацию надо делать на клиенте
Когда миллион записей, не целесообразно делать на клиенте.
Re: Ненужные сканы записей при rows [сообщение #5916 является ответом на сообщение #5914] Sat, 22 February 2025 00:59 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время не в онлайне  SD
Сообщений: 430
Зарегистрирован: August 2022
Senior Member
Оптимизатор не в курсе, что у тебя связь таблиц 1:1. 1000-я запись результата может быть как первой из ta_bundle, так и миллионной.
Re: Ненужные сканы записей при rows [сообщение #5922 является ответом на сообщение #5916] Mon, 24 February 2025 12:49 Переход к предыдущему сообщениюПереход к следующему сообщению
marcodor в настоящее время в онлайне  marcodor
Сообщений: 6
Зарегистрирован: June 2022
Junior Member
Связь не 1:1. В bundle документы, которые создают субьекты, entity.

Раз Firebird выдает план чтения из ta_entitу как unique scan:

    -> Filter
        -> Table "TA_ENTITY" as "C" Access By ID
            -> Bitmap
                -> Index "PK_TA_ENTITY" Unique Scan

То думаю Firebird знает что максимально можно вытащить одну запись из ta_entitу.
Так как у нас left join c максимум одна запись то это никак не влияет на rows, и соответственно нету смысла дергать эту таблицу при считывания первых 1000 записей из ta_bundle.
Re: Ненужные сканы записей при rows [сообщение #5928 является ответом на сообщение #5922] Mon, 24 February 2025 15:42 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время не в онлайне  SD
Сообщений: 430
Зарегистрирован: August 2022
Senior Member
marcodor писал(а) Mon, 24 February 2025 10:49
думаю Firebird знает что максимально можно вытащить одну запись из ta_entitу.
А ещё Firebird знает, что минимально это ноль записей. А сколько реально записей результата в первой тысяче - не знает.

Сам попробуй решить эту задачку собственным натуральным интеллектом: тысячная запись из ta_entity это первая, 500-я или тысячная запись результата? Сколько ещё записей надо пропускать после неё?
Re: Ненужные сканы записей при rows [сообщение #5930 является ответом на сообщение #5928] Mon, 24 February 2025 18:09 Переход к предыдущему сообщению
marcodor в настоящее время в онлайне  marcodor
Сообщений: 6
Зарегистрирован: June 2022
Junior Member
SD, еще раз, у нас выборка из ta_bundle, там ограничение по rows, и там важно сколько записей пропустить, и какие дальше выдавать клиенту.

Дальше для каждой записи из ta_bundle которое попали в rows мы делаем left join ta_entity и берем имя компании, то есть она никак не влияет на общее количество выданных записей и очередность. Или c left join ta_entity, или без, те же записи будут из ta_bundle.

Так вот, почему Firebird читает и для пропущенных записей (первая тысяча) из дополнительной таблицы ta_entity, непонятно, ведь она никак не влияет на rows.
Предыдущая тема: Непонятное изменение плана
Следующая тема: Полнотекстовый поиск для Firebird
Переход к форуму:
  


Текущее время: Mon Feb 24 20:12:35 GMT+3 2025

Общее время, затраченное на создание страницы: 0.01035 секунд