powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
25 сообщений из 46, страница 1 из 2
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706493
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"И снова здравствуйте!".

При очередном перечитывании Писания : 1.2.3. Навигация по индексу

Индексная навигация есть ни что иное, как последовательное сканирование ключей индекса. А так как для каждой записи серверу надо выполнить фетч записи и проверить ее видимость для нашей транзакции, то данная операция выходит достаточно дорогой.
. . .
Основное отличие индексной навигации от сканирования (описанного в пункте 1.2.2) заключается в отсутствии битовой карты между сканированием индекса и доступом к записи через ее идентификатор. Причина понятна - сортировка записей по физическим номерам в данном случае противопоказана. Из этого можно сделать вывод, что при индекс сканируется по мере фетча с клиента, а не "за раз" (как в случае использования битовой карты).- внезапно вспых вопрос.

Почему нельзя сначала пройтись по всем ключикам (с учётом where / rows ограничений, если они есть) и затолкать ID'шники записей в структуру типа TreeSet, которую по окончании сканирования индеска можно спокойно юзать для обхода записей в порядке возрастания их ID - ?
Да, понятно, что такой селект не выдаст клиенту ни одной строки до тех пор, пока не доберётся до последнего ключа и не начнёт выдавать содержимое TreeSet'a. Но селект ведь не только для выдачи результата клиенту юзается, а еще и просто для обработки строк в нужном порядке (т.е. курсором: for select ... from <T> where ... ORDER BY <F1, F2> as cursor C do ...)
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706496
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидПочему нельзя сначала пройтись по всем ключикам (с учётом where / rows ограничений, если они есть) и затолкать ID'шники записей в структуру типа TreeSet, которую по окончании сканирования индеска можно спокойно юзать для обхода записей в порядке возрастания их ID - ?

лучше ответь зачем это нужно
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706510
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что "зачем" ? Уменьшение числа random IO ?
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706513
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

кхе... порядок IDшников записей далеко не всегда (читай почти никогда, если это не ПК) совпадает с порядком ключей сортировки
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706514
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

даже ПК это не гарантирует. А кластерных индексов (Index Organized Table) в FB нету
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706521
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денискхе... порядок IDшников записей далеко не всегда (читай почти никогда, если это не ПК) совпадает с порядком ключей сортировкиНу так я про то и говорю! Раз он не совпадает, значит, надо сначала пройтись по индексу и каждый ID записи, который там будет встречен, помещать предварительно в TreeSet. И только после окончания навигации начинать выталкивать из TreeSet'a его содержимое.

Допустим, в индексе на страницах 123 и 124 сидят следующие ключи с ID'шниками:
index page =>123123123123124124124124index keys =>abcabcdbcdebcdefbcdfabcdfbbczbcz2rec IDs =>65432112345678901265002112159014999991112

Навигация начинается с левого ключа, т.е. с 'abc'. Там ID'шник = 654321 - помещаем его в TreeSet, но НЕ выдаём ничего пока что клиенту.
Далее переходим к ключу 'abcd', там ID'шник = 123456. Добавляем его в TreeSet, содержимое этого дерева будет теперь таким, что его итерация по его элементам выдаст (автоматом) их так: 123456, 654321.
Затем переходим дальше, к ключу 'bcde', там ID = 789012, и т.д.

В результате, по окончании этого процесса TreeSet будет таким, что итератор по нему выдаст элементы (ID'шники записей) в порядке их возрастания:
TreeSet iter.next()21212345615901465002165432178901299999111
И вот только тут, на этапе итерации по этому дереву, начинаем проверять видимость записей нашей транзакции и выдаём их на гор а , если сиё допускается. И обходим эти записи уже в порядке возрастания ID'шников.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706526
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

ну так порядок то будет не тот. Мы хотели вернуть записи в порядке ключей индексы, а после твоего алгоритма они нам вернутся в порядке расположения на диске.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706527
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидИ обходим эти записи уже в порядке возрастания ID'шников
И в какое место эти записи засунет пользователь, если он их просил совсем в другом порядке?..

То, о чём ты говоришь, это есть план INDEX. Который от ORDER несколько отличается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706528
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисну так порядок то будет не тот. а, тьфу... точно :-)
ну ладно, значит не судьба...
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706530
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я в печальке большой: не могу в одном месте избавиться от этого PLAN ORDER'a, бызнес-логика его требует.
И именно из-за него получаю совершенно дикие значения по произв-сти в трейсе.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706531
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидИ именно из-за него получаю совершенно дикие значения по произв-сти в
трейсе.
Кэш увеличь, чтобы нужный индекс в него помещался.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706536
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovТаблоидИ именно из-за него получаю совершенно дикие значения по произв-сти в трейсе.Кэш увеличь, чтобы нужный индекс в него помещался.
Кеш в SS поставил давно уже 512К, в трейсе при таком значении практически никогда не лезут read(s)>0.
А в SC пробовал и с кешем 16384 (больше не задавал, вряд ли такое увидишь в реале :)), но read(s)>0 периодически прут.
И сильно подозреваю, что даже если выставить в SC еще бОльший кеш ради истребления reads'ов - не поможет. Ибо SS тому пример.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706546
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидне могу в одном месте избавиться от этого PLAN ORDER'a, бызнес-логика его требует.

бизнес логика не может требовать какого то плана. Сортировки может, но не плана. Если это связано с твоим тестом OLTP скажи в каком месте, может идеи какие придут.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706549
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидне могу в одном месте избавиться от этого PLAN ORDER'a
насколько я в курсе, всегда можно избавиться от PLAN ORDER, только он поменяется на PLAN SORT. если при ORDER дофига random io, то SORT будет хорошо.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706595
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

там есть две процедурки, отвечающие за сторнирование количеств и стоимостей: sp_make_qty_storno & sp_make_cost_storno.
У них (в твоей версии теста) курсоры, обрабатывающие строки, делают это с PLAN ORDER. Сколько я не крутил-мутил с индексами, ничего там не улучшилось.
Курсорный запрос вида:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
            select
                 q.rdb$db_key as dbkey
                ,q.id
                ,q.doc_id as snd_list_id
                ,q.snd_id as snd_data_id
                ,q.snd_qty
                ,q.snd_purchase
                ,q.snd_retail
                ,q.snd_optype_id
                ,q.rcv_optype_id
            from qdistr q
            where
                  q.snd_optype_id = :snd_optype_id
                  and q.rcv_optype_id  = :rcv_optype_id
                  and q.ware_id = :ware_id
            order by q.doc_id, q.snd_id
            as cursor cq

- вгонял всё в гроб.
После добавления волшебного "плюс-нолика" в его order by всё залетало, ускорение в десятки раз.
Но это и другие исправления я еще тебе не высылал.

Однако, остались еще режимы, где PLAN ORDER таки требуется. Это выбор случайных документов для обработки - то, что делает fn_get_random_id через вот то: select id from <view_for_random_search> where id >= :x ORDER BY ID rows 1.
Почесав репу, я догадался, что вряде случаев можно и здесь убрать ORDER BY, потому что как только документ успешно залочен и взят в обработку, то при успешном её завершении он - возможно - исчезнет из видимости вьюхи <view_for_random_search>, т.к. перейдёт в такое состояние, когда по нему "всё сторнировано".
Но это будет НЕ СРАЗУ, а при многократных обработках выбранного док-та, т.к. за один присест с него сдёргивается для сторнирования не всё кол-во. Поэтому мне совсем не нравится этот подход, ибо костыль же, явный и убогий.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706596
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvТаблоидне могу в одном месте избавиться от этого PLAN ORDER'aнасколько я в курсе, всегда можно избавиться от PLAN ORDER, только он поменяется на PLAN SORT. если при ORDER дофига random io, то SORT будет хорошо.Можно, ес-сно. Но только если объем записей для SORT'a не очень большой. Именно так у мну, к щясью, и происходит.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706599
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

как раз когда есть ограничитель rows, да ещё и стоит там всего одна запись, PLAN ORDER будет эффективней чем SORT. Для трёшки вроде обещали сделать оптимизацию по-умолчанию для случая когда выбираются все записи. Сейчас это заметно когда есть JOIN. Оптимизатор меняет порядок соединения, если есть ограничитель ROWS.

Код: sql
1.
2.
3.
4.
5.
select horse.name,
       color.name
from horse
join color on horse.code_color = color.code_color
order by horse.name



PLAN SORT (JOIN (COLOR NATURAL, HORSE INDEX (FK_HORSE_COLOR)))

Код: sql
1.
2.
3.
4.
5.
select horse.name,
       color.name
from horse
join color on horse.code_color = color.code_color
order by horse.name rows 1



PLAN JOIN (HORSE ORDER HORSE_IDX_NAME, COLOR INDEX (PK_COLOR))

Правда сейчас абсолютно пофиг сколько я там укажу в rows хоть 10e9 план будет выбран второй.

Может тебе сей пример чем и поможет
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706603
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидну ладно, значит не судьба...А нет, стоп. Всё таки - судьба! :-)
Формируем битмап для хранения ID'шников, а также Tree Map , в котором:
<Key> - это результат вычисления для каждой записи выражения ORDER BY (т.е. значений одного или нескольких полей);
<Val> - это все прочие поля, не указанные в ORDER BY (кроме блобов, ес-сно; для них туда пишем только указатели).

Стартуем так, как делается при PLAN INDEX, в итоге будет сформирован битмап.
Далее, по нему делаем обход записей в порядке возрастания ID'шников, вытаскивая из записей все поля, которые были перечислены в ORDER BY и в SELECT-секции.

Для каждой такой записи проверяем её видимость текущей транзакции и если Ок, то заполняем <key> & <val> нашего TreeMap'a.

А затем - вываливаем вызывателю содержимое TreeMap'a, вызывая его итератор.

В итоге получаем:
1) однократное посещение записей и только в порядке возрастания их ID;
2) вывод из TreeMap'a идёт в том порядке, что задан был в ORDER BY.

Минус вижу только один: доп. расход памяти. Но в наш суровый век дешёвых терабайтов это не должно быть существенным.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706605
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

и чем это лучше чем сортировка в памяти (не навигация по индексу)
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706606
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денискак раз когда есть ограничитель rows, да ещё и стоит там всего одна запись, PLAN ORDER будет эффективней чем SORT. Я не увидел этой эффективности, когда база под нагрузкой.
Именно на запросах вида select ID from <view> where ID >= :x ORDER BY ID rows 1 неоднократно получал в трейсе то 5, а то 10 сек. И это при том, что ORDER BY - по первичному ключу, т.е. у нас достаточно большая вероятность того, что физ. порядок следования записей соотв-вует индексному.
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706607
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Дениси чем это лучше чем сортировка в памяти (не навигация по индексу)Хм... не знаю, сравнивать надо. Но один плюсик всё же есть: не нужно будет костыли всовывать везде (я про "+0").
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706609
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

значит у тебя вьюха хитрая. На простой таблице выигрыш просто огромный

Код: sql
1.
2.
3.
4.
select code_horse
from horse
where code_horse >= 1100000
order by horse.code_horse rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN (HORSE ORDER PK_HORSE)

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 16ms
Среднее время на получение одной записи = 16,00 ms
Current memory = 279 747 240
Max memory = 279 823 208
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 8

Код: sql
1.
2.
3.
4.
select code_horse
from horse
where code_horse >= 1100000
order by horse.code_horse+0 rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN SORT (HORSE INDEX (PK_HORSE))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 63ms
Среднее время на получение одной записи = 63,00 ms
Current memory = 279 793 464
Max memory = 281 892 944
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 54 861
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706619
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисзначит у тебя вьюха хитрая. Не, примитивизм сплошной:
Код: sql
1.
2.
3.
4.
5.
6.
create or alter view v_cancel_customer_reserve as
select h.id
from doc_list h
where
    h.optype_id = fn_oper_retail_reserve()
;

Где fn_oper_retail_reserve() - детерминистик-функция, лезет в базу только при первом своём вызове. При последующих возвращает ID операции, сохранённый у себя в кошельке. И даже если заменить её на тупой литерал (у мну - 3000), не поможет, не в ней дело.

Симонов ДенисНа простой таблице выигрыш просто огромныйКак-то не очень сильно бросилось в глаза... 16 мс против 63 ? это ты ведь в моно-коннекте сделал, так ?
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706621
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидКак-то не очень сильно бросилось в глаза... 16 мс против 63 ? это ты ведь в моно-коннекте сделал, так ?

это второй раз когда всё уже в кеш всосалось. Посмотри на количество фетчей.

Когда указана инструкция rows 1, то огромного random IO быть не должно, так как после первого фетча всё прекратится. Разве что приходится целиком прочитать индекс и то в твоём случае должен быть Range Scan

Код: sql
1.
2.
3.
4.
select h.id
from doc_list h
where
    h.optype_id = fn_oper_retail_reserve() -- это может помешать



тут скорее всего для optype_id есть дополнительный индекс
вот тебе для сравнения

Код: sql
1.
2.
3.
4.
5.
select code_horse
from horse
where code_horse >= 1100000 and
      code_breed = 65
order by horse.code_horse rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN (HORSE ORDER PK_HORSE INDEX (FK_HORSE_BREED))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 15ms
Среднее время на получение одной записи = 15,00 ms
Current memory = 279 843 232
Max memory = 281 658 848
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 34

Чтений из кэша стало больше 34 vs 8
...
Рейтинг: 0 / 0
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
    #38706634
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денистут скорее всего для optype_id есть дополнительный индекс есть, конечно же (см DDL, их есть у тебя).
Только вот какое дело: не вижу я чё-то при работе в моноконнекте никаких осязаемых преимуществ order by id+0 над order by id.

Вот пример.
DDL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
-- create sequence g;
alter sequence g restart with 0; commit;
recreate table t(id int, x int); commit;
recreate global temporary table gtt(id int, r int) on commit delete rows; commit;
create index gtt_r on gtt(r); commit;

set term ^;
execute block as
declare variable n int = 500000;
begin
  while (n>0) do insert into gtt(id, r) values( gen_id(g,1), rand()*1000000 ) returning :n-1 into n;
end
^set term ;^
insert into t(id,x) select id, rand()*9999 from gtt order by r;
commit;

create index t_id on t(id);
create index t_x on t(x);
commit;

recreate table t_log(trn_id int default current_transaction primary key, done_searchs int, avg_ms_for_one_search int);
commit;

drop table gtt;
commit;
(будет создана таблица t(id, x) с 500 тыс записями, но физ. расположение строк в ней будет отвратительным с т.зр. навигации по ID-индексу.

Test:
Код: 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.
35.
execute block
as
  declare n int = 1000;
  declare i int;
  declare v_min_x int;
  declare v_max_x int;
  declare v_min_id double precision;
  declare v_max_id double precision;
  declare v_cur_id double precision;
  declare v_stt varchar(80);
  declare t0 timestamp;
  declare x int;
  declare c smallint = 1;
begin
   select min(id)-0.5 from t into v_min_id;
   select max(id)+0.5 from t into v_max_id;
   select min(x) from t into v_min_x;
   select max(x) from t into v_max_x;
   x=v_min_x + rand()*( v_max_x - v_min_x );
   if (c = 1) then
     v_stt = 'select id from t where x = :x and id >= :y ORDER BY id rows 1';
   else
     v_stt = 'select id from t where x = :x and id >= :y ORDER BY id+0 rows 1';

   t0='now';
   i=n;
   while (i > 0) do
   begin
      execute statement (v_stt) ( x := :x, y := v_min_id + rand()*( v_max_id - v_min_id ) ) into v_cur_id;
      i = i-1;
   end
   update or insert into t_log(trn_id, done_searchs, avg_ms_for_one_search)
   values( current_transaction, :n, datediff(millisecond from :t0 to cast('now' as timestamp)) / :n );

end



Запусти у себя сначала с "declare c smallint = 1;", а затем поменяй на "declare c smallint = 2;", чтобы вызовы были с order by id+0.
Я разницу как-то не ощутил.

Может, в сильно-конкурентной среде, когда в таблицу `t` будут падать новые строки, будет всё по-другому, не знаю.
...
Рейтинг: 0 / 0
25 сообщений из 46, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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