powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Запись из середины таблицы и ещё 199 после неё...
3 сообщений из 3, страница 1 из 1
Запись из середины таблицы и ещё 199 после неё...
    #32077602
vskv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ситуация:
Имеем базу на 8i и клиентское приложение на Дельфи, которое к этой базе подключается.

Юзвери и админы пользуют приложение и радуются жизни, пока не приходит час Х, когда у кого-нибудь не возникает нужда [оперативно] изменить пару атрибутов в клиентской записи и не вызывают форму "ручной ввод инфомации".

Раньше с сервера клиент fetch'ил все записи, что вызывало многочисленные нарекания со стороны юзверей "медленно загружется" и админов "PGA соотв. процесса вырастает до 250М и освобождается только, когда юзверь закрывает клиента, а не когда он выходит из формы". В итоге решили дополнить запрос предикатом "rownum<=200" -- всё равно все записи не нужны...

Фон:
Выборка идёт из трёхэтажной контрукции.

На первом этаже идёт view CARDS_R
Код: plaintext
1.
2.
3.
select * from CARDS C 
      where C.CENTRE in 
           (select CENTRE from USER_CNTRS UC 
            where match_user(UC.USERNAME)


На втором этаже идёт view CARDS_MR
Код: plaintext
1.
select * from CARDS_R
      where check_context('CARDS_R')='T'


И только на третьем идёт собственно запрос приложения с конструкцией
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select  /*+ INDEX(C CARDS_IND1) */  
   C.ROWID, C.CENTRE, C.CARD, C.STATUS||'-'||ST.ST_TEXT
from CARDS_MR C, STATUS_D ST
where C.CENTRE= :p_centre and C.CARD >= :p_card
and C.STATUS=ST.ST_NUMB
and rownum<= 200 
order by CENTRE, CARD


Есть три индекса, из них в игре участвуют только два: CARDS_PK по CENTRE+CARD и CARDS_IND1 только по CARD.

Запрос используется для заполнения полей формы (первая запись из выборки) и списка (все остальные 199 записей).

Проблема:
На одной из рабочих баз при указании конкретного знечения CENTRE+CARD запрос стал выдавать [ 200 записей, в возрастающем порядке, следующих заведомо за искомой записью ], но, к сожалению, не включая искомую...
В тестовых условиях удалось воспроизвести только безнадёжно испортив хинт -- указав /*+ INDEX(CX CARDS_IND1) */ -- прижатый RULE, без хинта и с правильным хинтом запрос выдавал 200 последовательных записей начиная с искомой.

Собственно проблема:
После исправления запроса, чтобы в хинте использовалось правильное название алиаса вьюшки, проблема на рабочей базе не исправилась...

Ещё пара достаточно странных симптомов:

все планы (и RULE, и без хинта, и с правильным хинтом, и с неправильным) показывают использование индекса CARDS_IND1

планы с правильным хинтом и с неправильным абсолютно совпадают (как на тесте, так и на рабочей); статистика собрана (compute) принудительно (на первых минутах выяснения обстоятельств)

оба плана показывают использование HASH JOIN после RANGE SCAN по CARDS_IND1

неправильная выборка не является сплошной в том смысле, что являет из себя просто 200 точек из упорядоченной последовательности -- типа 20, 32, 45, 59, 64..., а не 7, 8, 9, 10, 11...

Вопросы

Почему оно начало так нестабильно вести себя на другом наборе данных

Как правильно указывать название алиаса в хинте, если используется представление

Как правильно оформить желаемое в виде "бронебойного" SQL запроса
...
Рейтинг: 0 / 0
Запись из середины таблицы и ещё 199 после неё...
    #32078209
DimaR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
во первых не пологаться на хинты в плане порядка записей
во вторых сортировка в
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select  /*+ INDEX(C CARDS_IND1) */  
   C.ROWID, C.CENTRE, C.CARD, C.STATUS||'-'||ST.ST_TEXT
from CARDS_MR C, STATUS_D ST
where C.CENTRE= :p_centre and C.CARD >= :p_card
and C.STATUS=ST.ST_NUMB
and rownum<= 200 
order by CENTRE, CARD

идет после выборки 200 записей, поэтому скорее
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select * from
(select  /*+ INDEX(C CARDS_IND1) */  
   C.ROWID, C.CENTRE, C.CARD, C.STATUS||'-'||ST.ST_TEXT
from CARDS_MR C, STATUS_D ST
where C.CENTRE= :p_centre and C.CARD >= :p_card
and C.STATUS=ST.ST_NUMB
order by CENTRE, CARD)
where rownum<= 200 
...
Рейтинг: 0 / 0
Запись из середины таблицы и ещё 199 после неё...
    #32078766
vskv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как всё прозаично всё получилось...

Выяснилось, что есть ещё индекс CARDS_IND3 по CENTRE+GRP. И Оракул посчитал, что использовать этот индекс дешевле -- у него селективность меньше. При указании OPTIMIZER_MODE=FIRST_ROWS используется индекс по PK, а вот при ALL_ROWS -- неселективный по префиксу.

Кстати, это ещё камешек в огород тех, кто предлагает получать запись предшествующую какой-либо с помощью хинта INDEX_DESC -- Оракул запросто игнорирует хинт, если у него есть на то более веские аргументы...
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Запись из середины таблицы и ещё 199 после неё...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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