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

Начало » Использование СУБД » Firebird, HQbird, InterBase » Ненужные сканы записей при rows
Ненужные сканы записей при rows [сообщение #5911] Fri, 21 February 2025 12:49 Переход к следующему сообщению
marcodor в настоящее время не в онлайне  marcodor
Сообщений: 4
Зарегистрирован: 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
Сообщений: 4
Зарегистрирован: 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
Сообщений: 428
Зарегистрирован: 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
Сообщений: 4
Зарегистрирован: 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
Сообщений: 428
Зарегистрирован: August 2022
Senior Member
Оптимизатор не в курсе, что у тебя связь таблиц 1:1. 1000-я запись результата может быть как первой из ta_bundle, так и миллионной.
Предыдущая тема: Непонятное изменение плана
Следующая тема: Полнотекстовый поиск для Firebird
Переход к форуму:
  


Текущее время: Sat Feb 22 23:59:40 GMT+3 2025

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