powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Непонятки с оптимизатором 2.5.3
59 сообщений из 59, показаны все 3 страниц
Непонятки с оптимизатором 2.5.3
    #38386750
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сервер LI-V6.3.3.26655 Firebird 2.5
клиент 2.5.1.26351
IBExpert

Есть таблица (лишние поля убрал)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE ACCOUNT_STATE (
    CODE          INTEGER NOT NULL,
    ACCOUNTCODE  BIGINT NOT NULL,
    ENDDATE     DATE,
.......
);

ALTER TABLE ACCOUNT_STATE ADD CONSTRAINT PK_ACCOUNT_STATE PRIMARY KEY (CODE);

CREATE DESCENDING INDEX ACCOUNT_STATE_ACC_ED_DESC ON ACCOUNT_STATE (ACCOUNTCODE, ENDDATE);



Запрос
Код: sql
1.
2.
3.
4.
 select *
  from Account_State
  where Accountcode = :IAccount
    and (Enddate = :Idate1 or Enddate = :Idate2)


показывает план
PLAN (ACCOUNT_STATE INDEX (ACCOUNT_STATE_ACC_ED_DESC))

что для меня несколько неожиданно ибо я ожидал
PLAN (ACCOUNT_STATE INDEX (ACCOUNT_STATE_ACC_ED_DESC, ACCOUNT_STATE_ACC_ED_DESC))

Хочется узнать почему мои ожидания не оправдались. (И небольшое уточнение вопрос не про обходные пути)

зы. записей в таблице 268773
Статистика для обоих индексов 0,000003720611.....

Если нужна еще какая либо информация с удовольствием предоствлю
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386759
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m, на другой версии было иначе?

m7m
Код: sql
1.
CREATE ASCENDING INDEX ACCOUNT_STATE_ACC_ED_DESC ON ACCOUNT_STATE (ACCOUNTCODE, ENDDATE);


М? Так, теоретизирую.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386763
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

1. (Enddate = :Idate1 or Enddate = :Idate2) вырубает использование индекса (если бы он был только по Enddate)
2. Даже если бы там не было выражения, то с чего ты решил что индекс должен задействоваться дважды?
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386770
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис> 1. (Enddate = :Idate1 or Enddate = :Idate2) вырубает
Симонов Денис> использование индекса (если бы он был только по Enddate)

Ну здрасьте, приехали... Ты чего? :)
Если сложный предикат, а индекс
составной - да, наверное, возможны
нюансы, но не в таком простом кейсе.

P.S. Топик не читал.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386773
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanm7m, на другой версии было иначе?
Именно этот запрос - без понятия, у меня к сожалению сейчас нет возможности проверить на другой версии
Однако аналогичный запрос на другой таблице (только индекс там трех сегментный) работает ожидаемо для меня
(т.е. в плане дважды упоминается индекс)

wadmanm7m
Код: sql
1.
CREATE ASCENDING INDEX ACCOUNT_STATE_ACC_ED_DESC ON ACCOUNT_STATE (ACCOUNTCODE, ENDDATE);


М? Так, теоретизирую.
нет, никакие манипуляции с индексом, (asc, desc, добавление нового сегмента) не привели к ожидаемым мною результатам
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386782
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По сабжу - на первое поле индекса нет никаких доп.ограничений, уникальности?

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386785
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустам,

тьфу блин. Перепутал с другим случаем когда field = :param1 or param1 is null.

Думаю что в этом случае оптимизатор решил что выгодней использовать только часть составного индекса. Тут для отвта нужны сведения по селективности отдельных сегментов.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386788
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7mЕсли нужна еще какая либо информация с удовольствием предоставлю
план на 2.5.2 не помешает. И на 2.5.0 заодно.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386790
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7mСтатистика для обоих индексов 0,000003720611.....
ты забыл, что 2.5 анализирует селективность по всем сегментам композитного индекса, которая может быть хуже, чем суммарная селективность композита. Раньше композиты были вредны именно этим.

Возможно, что по второму сегменту селективность плохая, и поэтому оптимизатор решил не париться, два раза сканируя весь индекс, а потом объединяя битмапы по OR, а просто отобрать записи по первому сегменту, причем один раз.
В принципе, я бы и от предыдущих оптимизаторов ожидал подобного поведения.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386803
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrm7mЕсли нужна еще какая либо информация с удовольствием предоставлю
план на 2.5.2 не помешает. И на 2.5.0 заодно.
Немного проблематично :(
(постараюсь завтра-послезавтра)

и еще одно уточнение

запрос
Код: sql
1.
2.
3.
4.
select *
  from Account_State
  where (Accountcode = :IAccount and Enddate = :Idate1) or
  (Accountcode = :IAccount and Enddate = :Idate2)


работает ожидаемо
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386816
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

Выполни следующий запрос

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT SEG.RDB$INDEX_NAME AS INDEX_NAME,
       SEG.RDB$FIELD_NAME AS FIELD_NAME,
       SEG.RDB$STATISTICS AS STAT
FROM RDB$INDEX_SEGMENTS SEG
WHERE SEG.RDB$INDEX_NAME = 'ACCOUNT_STATE_ACC_ED_DESC'
UNION ALL
SELECT I.RDB$INDEX_NAME AS INDEX_NAME,
       NULL AS FIELD_NAME,
       I.RDB$STATISTICS AS STAT
FROM RDB$INDICES I
WHERE I.RDB$INDEX_NAME = 'ACCOUNT_STATE_ACC_ED_DESC'



Результат выложи сюда
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386838
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m> работает ожидаемо

Забавненько. ДЕ, оптимизатор такие обманы пока не умеет замечать?

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386841
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

кол-во индексных чтений и записей в результате отличаются ?
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386859
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамДЕ, оптимизатор такие обманы пока не умеет замечать?
смотря что ты считаешь обманом :-) Второй вариант абсолютно понятен оптимизатору, а первый "обман" - нет. Один и тот же предикат нельзя использовать для двух индексных выборок, отсюда и результат в первом посте. Уверен что во всех версиях ФБ план будет такой же, т.е. используется лишь первый сегмент. А развернуть свернутую бинарную логику оптимизатор не умеет.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386892
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladm7m,

кол-во индексных чтений и записей в результате отличаются ?
Да

запрос
Код: sql
1.
2.
3.
4.
 select *
   from Account_State
  where Accountcode = 240472
    and (Enddate = date '01.01.2013' or Enddate = date '31.01.2013')


возвращает 0 записей 16 индексных чтений

запрос
Код: sql
1.
2.
3.
4.
 select *
   from Account_State
  where (Accountcode = 240472 and Enddate = date '01.01.2013') OR
           (Accountcode = 240472 and Enddate = date '31.01.2013')


возвращает 0 записей 0 индексных чтений
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386917
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисm7m,

Выполни следующий запрос

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT SEG.RDB$INDEX_NAME AS INDEX_NAME,
       SEG.RDB$FIELD_NAME AS FIELD_NAME,
       SEG.RDB$STATISTICS AS STAT
FROM RDB$INDEX_SEGMENTS SEG
WHERE SEG.RDB$INDEX_NAME = 'ACCOUNT_STATE_ACC_ED_DESC'
UNION ALL
SELECT I.RDB$INDEX_NAME AS INDEX_NAME,
       NULL AS FIELD_NAME,
       I.RDB$STATISTICS AS STAT
FROM RDB$INDICES I
WHERE I.RDB$INDEX_NAME = 'ACCOUNT_STATE_ACC_ED_DESC'



Результат выложи сюда

Код: plaintext
1.
2.
3.
4.
INDEX_NAME	             FIELD_NAME	                 STAT
-----------------------------------------------------------------
ACCOUNT_STATE_ACC_ED_DESC	ENDDATE    	3.72061185771599E-6
ACCOUNT_STATE_ACC_ED_DESC	ACCOUNTCODE	7.78846515459009E-6
ACCOUNT_STATE_ACC_ED_DESC              		3.72061185771599E-6
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386938
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,
после поста dimitr 14794983 всё уже понятно. Может быть в трёшке оптимизатор будет умнее в таких случаях.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386942
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrГаджимурадов РустамДЕ, оптимизатор такие обманы пока не умеет замечать?
смотря что ты считаешь обманом :-) Второй вариант абсолютно понятен оптимизатору, а первый "обман" - нет. Один и тот же предикат нельзя использовать для двух индексных выборок, отсюда и результат в первом посте. Уверен что во всех версиях ФБ план будет такой же, т.е. используется лишь первый сегмент. А развернуть свернутую бинарную логику оптимизатор не умеет.

Ну вот немного другая ситуация

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE TABLE ACCOUNT_SERVICE (
    CODE              INTEGER NOT NULL ,
    ACCOUNTCODE       BIGINT NOT NULL ,
    SERVICE         INTEGER NOT NULL,
    ACCOUNT_PIPECODE   INTEGER NOT NULL ,
    ENDDATE        DATE,
.......
);

ALTER TABLE ACCOUNT_SERVICE ADD CONSTRAINT PK_ACCOUNT_SERVICE PRIMARY KEY (CODE);

CREATE DESCENDING INDEX ACCOUNT_SERVICE_ACC_ENDDATE ON ACCOUNT_SERVICE (ACCOUNTCODE, ACCOUNT_PIPECODE, ENDDATE);
CREATE INDEX ACCOUNT_SERVICE_PIPE_SERVICE ON ACCOUNT_SERVICE (ACCOUNT_PIPECODE, SERVICE);




запрос
Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where Accountcode = 251696
    and Account_Pipecode = 307817
    and (Enddate = date '01.01.2013' or Enddate = date '31.01.2013')



PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))

и получается что развернуть свернутую бинарную логику оптимизатор умеет
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386958
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисm7m,
после поста dimitr 14794983 всё уже понятно. Может быть в трёшке оптимизатор будет умнее в таких случаях.

ну оно вроде так, однако 14795294 практически тоже (ну другая таблица, ну три сегмента, но оптимизатор разобрался)
и если-бы он здесь не разобрался то исходный вопрос не поднимался бы

(хронологически сначала был разбор полетов с запросом 14795294 , а потом с 14794643 )
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386962
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

Это не тоже самое. Здесь у тебя оптимизатор выбрал план по отдельным сегментам индекса
ACCOUNT_SERVICE_ACC_ENDDATE один для поля ACCOUNTCODE, второй - ACCOUNT_PIPECODE
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386969
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr,

а в трёшке в плане будет как-нибудь отражено какой именно сегмент индекса был выбран в таких случаях?
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386983
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

да, будет (в расширенном плане)
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386988
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисm7m,

Это не тоже самое. Здесь у тебя оптимизатор выбрал план по отдельным сегментам индекса
ACCOUNT_SERVICE_ACC_ENDDATE один для поля ACCOUNTCODE, второй - ACCOUNT_PIPECODE
какое тогда будет объяснение для
Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where Accountcode = 251696
    and Account_Pipecode = 307817
    and Enddate = date '01.01.2013'


PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE))
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386992
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

ну а здесь всё понятно оптимизатор выбрал индекс целиком, а не по сегментам (раскрывать ничего не потребовалось)
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38386995
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7mи получается что развернуть свернутую бинарную логику оптимизатор умеет
гммм, ты меня в тупик поставил :) Может я и ошибся выше. Примеры обоих случаев можешь предоставить?
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387002
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr,

Мой пост 14795355 это не объясняет?
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387003
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисЭто не тоже самое. Здесь у тебя оптимизатор выбрал план по отдельным сегментам индекса
ACCOUNT_SERVICE_ACC_ENDDATE один для поля ACCOUNTCODE, второй - ACCOUNT_PIPECODEДенис, ты не прав. Подумай и объясни нам - почему :)
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387017
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrm7mи получается что развернуть свернутую бинарную логику оптимизатор умеет
гммм, ты меня в тупик поставил :) Может я и ошибся выше. Примеры обоих случаев можешь предоставить?

Примеры, в смысле базу с данными на котором это воспроизводится???
думаю что да, ну опять-же немного попозже, надо всё лишнее убрать, а это процесс длительный
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387040
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

ок, буду ждать
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387045
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad,

Я действительно неправ. Но объяснить не могу.

Код: sql
1.
2.
3.
4.
select *
  from Account_Service
  where Accountcode = 1032846809
    and Account_Pipecode = 1700738615



PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE))

Вроде вспоминается что-то про битовые маски. Надо бы конечно ещё раз перечитать статью о методах доступа.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387126
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr> ок, буду ждать

Только сообщить результаты исследования не забудь, пожалуйста.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387135
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустам,

конечно. Даже если я таки ошибся выше, то IMHO причина будет банальна - что-то со статистикой. В баг я пока не верю, но посмотрим.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387150
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE ACCOUNT_SERVICE (
    CODE              INTEGER NOT NULL ,
    ACCOUNTCODE       BIGINT NOT NULL ,
    SERVICE         INTEGER NOT NULL,
    ACCOUNT_PIPECODE   INTEGER NOT NULL ,
    ENDDATE        DATE
);

ALTER TABLE ACCOUNT_SERVICE ADD CONSTRAINT PK_ACCOUNT_SERVICE PRIMARY KEY (CODE);

CREATE DESCENDING INDEX ACCOUNT_SERVICE_ACC_ENDDATE ON ACCOUNT_SERVICE (ACCOUNTCODE, ACCOUNT_PIPECODE, ENDDATE);
CREATE INDEX ACCOUNT_SERVICE_PIPE_SERVICE ON ACCOUNT_SERVICE (ACCOUNT_PIPECODE, SERVICE);



Залил случайные данные 10000 строк через генератор в IBExpert. Обновил статистику.

Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where Accountcode = 1032846809
    and Account_Pipecode = 1700738615
    and (Enddate = date '30.09.2013' or Enddate = date '31.01.2013')



PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE))
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387153
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

правда версия 2.5.2.26539. Приду домой проверю на свежем снапшоте.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387222
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

на снапшоте 2.5.3 тоже самое. Что-то ты не договариваешь. Не удаётся мне получить план
PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387226
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисm7m,

на снапшоте 2.5.3 тоже самое. Что-то ты не договариваешь. Не удаётся мне получить план
PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))

структуры таблиц, запросы и планы копировал из IBEpert'а
завтра еще раз на свежую голову всё проверю
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387314
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисЗалил случайные данные 10000 строк через генератор
лабуда.
1. надо начинать с миллиона.
2. рандом тоже должен быть специфическим, чтобы дать желаемое количество дубликатов. Рандом по строке в 20 символов даст почти все уникальные значения.

Напомню, что селективность индекса, это 1/(Keys - TotalDup), т.е. 1/(всего_ключей - всего_минус_повторы).
например, 10к ключей, 1к повторов, это 1/(10000-9000).
Чем меньше повторов, тем больше значение стремится к нулю. При 100% повторов значение будет равно 1/(10000-9999) = 1. Это наихудше возможная селективность индекса.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387368
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv,

мы тут про случай когда оптимизатор разворачивает свёрнутую бинарную логику

ТС утверждал, что у него оба запроса по 3х сегментному индексу дают одинаковый план

Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where Accountcode = 1032846809
    and Account_Pipecode = 1700738615
    and (Enddate = date '30.09.2013' or Enddate = date '31.01.2013')


PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE))

Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where
    (Accountcode = 1032846809 and Account_Pipecode = 1700738615 and Enddate = date '30.09.2013') or
    (Accountcode = 1032846809 and Account_Pipecode = 1700738615 and Enddate = date '31.01.2013')


PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))

Мне такое сделать не удаётся. Хотя второй запрос даёт желаемый ТСом план.
Может конечно там какие-то нюансы.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387437
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Удалось воспроизвести

Код: sql
1.
2.
3.
4.
5.
select *
  from Account_Service
  where Accountcode = 1
    and Account_Pipecode = 2
    and (Enddate = date '30.09.2013' or Enddate = date '31.01.2013')



PLAN (ACCOUNT_SERVICE INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))

Сделал в Accountcode и Account_Pipecode всего одно значение. А дату равномерно распределённой. Так что похоже ничего там не раскрывается. Просто индекс берётся только по сегменту поля Enddate, т.к. по нему селективность выше.

Однако непонятно как это состыковывается предложением в статье о методах доступа

Дмитрий ЕмановИндексы могут быть простыми (односегментными) и составными (многосегментными или композитными). Следует отметить, что совокупность полей композитного индекса представляет собой единый ключ. Поиск в индексе может осуществляться как по ключу целиком, так и по его подстроке (подключу). Очевидно, что поиск по подключу допустим только для начальной части ключа (например, starting with или использование не всех сегментов композита). Если поиск осуществляется по всем сегментам индекса, то это называется полным совпадением (full match) ключа, иначе это частичное совпадение (partial match) ключа. Отсюда для композитного индекса по полям (A, B, C) следует, что:

1. он может быть использовать для предикатов (A = 0) или (A = 0 and B = 0) или (A = 0 and B = 0 and C = 0), но не может быть использован для предикатов (B = 0) или (C = 0) или (B = 0 and C = 0);
2. предикат (A = 0 and B > 0 and C = 0) приведет к частичному совпадению по двум сегментам, а предикат (A > 0 and B = 0) - к частичному совпадению всего по одному сегменту.

В частности "но не может быть использован для предикатов (B = 0) или (C = 0)"

Код: sql
1.
CREATE DESCENDING INDEX ACCOUNT_SERVICE_ACC_ENDDATE ON ACCOUNT_SERVICE (ACCOUNTCODE, ACCOUNT_PIPECODE, ENDDATE);



Тут вроде как поле ENDDATE стоит последним. Или я что-то не догнал.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387462
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
select *
  from Account_Service
  where (Enddate = date '30.09.2013' or Enddate = date '31.01.2013')


PLAN (ACCOUNT_SERVICE NATURAL)

Совсем я запутался. Вообщем предложение в статье верное. Тогда не понятно как получается выше указанный план.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387513
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7mструктуры таблиц, запросы и планы копировал из IBEpert'а
завтра еще раз на свежую голову всё проверю
Проверил, все свои слова подтверждаю
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387515
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrm7m,

ок, буду ждать

отправил
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387810
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
итак, разбор полетов

запрос 1 (проблемный):

Код: sql
1.
2.
3.
4.
5.
6.
select S.Code
from Account_State S
where S.Accountcode = 402752
  and (S.Enddate = date '01.01.2013' or S.Enddate = date '31.01.2013')

PLAN (S INDEX (ACCOUNT_STATE_ACC_ED_DESC))


смотрим посегментную селективность индекса:

Код: sql
1.
2.
3.
ACCOUNT_STATE_ACC_ED_DESC
  - ACCOUNTCODE = 7.7884651545900851e-06
  - ENDDATE = 3.7205979879217921e-06


видим, что использование последнего сегмента для выборки уменьшает ее размер (кардинальность) примерно в два раза. Т.е. объединение двух выборок по OR даст примерно ту же кардинальность, что и использование лишь первого сегмента однажды. Но при примерно равной стоимости выборки записей вариант с OR еще и удвоит стоимость чтения индекса, ибо будет два скана вместо одного. В попугаях там получается стоимость примерно 6 против 4 не в пользу варианта с OR-битмапом. Отсюда и результат.

запрос 2 (хороший):

Код: sql
1.
2.
3.
4.
5.
6.
7.
select S.Code
from Account_Service S
where S.Accountcode = 402752
  and S.Account_Pipecode = 1
  and (S.Enddate = date '01.01.2013' or S.Enddate = date '31.01.2013')

PLAN (S INDEX (ACCOUNT_SERVICE_ACC_ENDDATE, ACCOUNT_SERVICE_ACC_ENDDATE))


смотрим посегментную селективность индекса:

Код: sql
1.
2.
3.
4.
ACCOUNT_SERVICE_ACC_ENDDATE
 - ACCOUNTCODE = 7.7884651545900851e-06
 - ACCOUNT_PIPECODE = 4.3068916966149118e-06
 - ENDDATE = 1.0188310852754512e-06


видим, что использование последнего сегмента для выборки уменьшает ее размер (кардинальность) примерно в четыре раза. Т.е. объединение двух выборок по OR будет все еще в два раза дешевле, чем использование лишь первых двух сегментов однажды. Пусть с учетом стоимости индексных сканов это будет не в два, а лишь в полтора раза, но все равно дешевле.

а вот добавляя еще одно условие в OR мы уже выйдем на уровень стоимости первых двух сегментов, если не хуже. Что сервер наглядно демонстрирует, отказываясь делать OR-битмап при трех OR-условиях:

Код: sql
1.
2.
3.
4.
5.
6.
7.
select S.Code
from Account_Service S
where S.Accountcode = 402752
  and S.Account_Pipecode = 1
  and (S.Enddate = date '01.01.2013' or S.Enddate = date '15.01.2013' or S.Enddate = date '31.01.2013')

PLAN (S INDEX (ACCOUNT_SERVICE_ACC_ENDDATE))
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387811
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrитак, разбор полетовОсталось сравнить рантайм статистику для разных планов, чтобы понять - прав оптимизатор или нет :)
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387812
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrвидим, что использование последнего сегмента для выборкиЯ бы сказал "использование двух (всех) сегментов для выборки".
Ибо тут уже были абсурдные предположения, что можно использовать только второй сегмент для поиска...
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387823
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr> итак, разбор полетов

Судя по описанию, оптимизатор во всех случаях оказался прав?

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387826
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr,

Ага таки оптимизатор умеет разворачивать свёрнутую бинарную логику. Просто все мои предположения исходили из того, что он этого делать не может. Теперь всё понятно.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387835
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис> Ага таки оптимизатор умеет разворачивать свёрнутую бинарную логику

С чего это? Просто её выгоднее пустить по одному плану, а не по другому.
Это не совсем разворачивание, а просто подсчёт селективности сегментов.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387838
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустам,

По описанию то прав, но

m7mhvladm7m,

кол-во индексных чтений и записей в результате отличаются ?
Да

запрос
Код: sql
1.
2.
3.
4.
 select *
   from Account_State
  where Accountcode = 240472
    and (Enddate = date '01.01.2013' or Enddate = date '31.01.2013')


возвращает 0 записей 16 индексных чтений

запрос
Код: sql
1.
2.
3.
4.
 select *
   from Account_State
  where (Accountcode = 240472 and Enddate = date '01.01.2013') OR
           (Accountcode = 240472 and Enddate = date '31.01.2013')


возвращает 0 записей 0 индексных чтений
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387840
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамСудя по описанию, оптимизатор во всех случаях оказался прав?
по статистике прав, а как оно де-факто выйдет - ХЗ, зависит от реальных значений в полях. На предоставленной базе и именно этих константах в запросе он скорее неправ, но разница там субтильная (23 vs 27 фетчей).
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387843
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамС чего это? Просто её выгоднее пустить по одному плану, а не по другому.
Это не совсем разворачивание, а просто подсчёт селективности сегментов.

Всё понеслось вот с этого ответа. Я ведь сначала даже поинтересовался у ТС селективностью сегментов.

dimitrГаджимурадов РустамДЕ, оптимизатор такие обманы пока не умеет замечать?
смотря что ты считаешь обманом :-) Второй вариант абсолютно понятен оптимизатору, а первый "обман" - нет. Один и тот же предикат нельзя использовать для двух индексных выборок, отсюда и результат в первом посте. Уверен что во всех версиях ФБ план будет такой же, т.е. используется лишь первый сегмент. А развернуть свернутую бинарную логику оптимизатор не умеет.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387905
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr,

Спасибо!!!!

зы. Для себя я понял что в принципе всё в порядке.
и заставлять сервер использовать два раза индекс не буду :) :) :)
ибо тем самым не оставлю оптимизатору никакого выбора
тем более что (насколько я понимаю) по мере жизни базы селективность по первым сегментам
ACCOUNTCODE , ACCOUNT_PIPECODE будет ухудшаться (ибо количество их практически не изменится)
а по последнему сегменту - ENDDATE будет улучшаться
и рано или поздно наступит "счастье"
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387917
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitr> по статистике прав, а как оно де-факто выйдет - ХЗ, зависит от реальных значений в полях.

Так это везде так. На этапе построения плана есть ведь только селективность.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387925
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис> Я ведь сначала даже поинтересовался у ТС селективностью сегментов.

Так ДЕ же объяснил с конкретными цифрами.
Возможно мы по-разному понимаем понятие
разворачивания предиката - я (и ДЕ, AFAIU)
имел в виду следующее:

1. where A = :A and (B = :B1 or B = :B2) есть
сокращенный вариант развернутого
where A = :A and B = :B1 or A = :A and B = :B2.

2. Это ручной обман (подсказка) оптимизатора и
сам он такое (разворачивать предикат) не умеет.
Наверное, это можно добавить, но ХЗ насколько
это сложно и оправданно.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38387956
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустам,

Я именно так и понял. Хотя да, из слов ДЕ оптимизатор не разворачивает выражение. Но всё равно умеет использовать индекс дважды, если если стоимость получается более низкой.

Кстати по идее с использованием гистрограмм может получится другая оценка, но вроде их использование возможно только для сравнения с константами.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38390729
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мысль тут у меня появилась, насколько дурная не знаю

дабы не листать топик приведу исходный пост еще раз

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE ACCOUNT_STATE (
    CODE          INTEGER NOT NULL,
    ACCOUNTCODE  BIGINT NOT NULL,
    ENDDATE     DATE,
.......
);

ALTER TABLE ACCOUNT_STATE ADD CONSTRAINT PK_ACCOUNT_STATE PRIMARY KEY (CODE);

CREATE DESCENDING INDEX ACCOUNT_STATE_ACC_ED_DESC ON ACCOUNT_STATE (ACCOUNTCODE, ENDDATE);




Запрос

Код: sql
1.
2.
3.
4.
 select *
  from Account_State
  where Accountcode = :IAccount
    and (Enddate = :Idate1 or Enddate = :Idate2)



показывает план
PLAN (ACCOUNT_STATE INDEX (ACCOUNT_STATE_ACC_ED_DESC))

я ожидал
PLAN (ACCOUNT_STATE INDEX (ACCOUNT_STATE_ACC_ED_DESC, ACCOUNT_STATE_ACC_ED_DESC))


зы. записей в таблице 268773
Статистика для обоих индексов 0,000003720611.....


с планами и причинами таких планов объяснили, все понятно
но вот возник вопрос в связи с выделенным текстом
Если создать уникальный индекс
ALTER TABLE ACCOUNT_STATE ADD CONSTRAINT UNQ1_ACCOUNT_STATE UNIQUE (ACCOUNTCODE, ENDDATE);
то оптимизатор выбирает план
PLAN (ACCOUNT_STATE INDEX (UNQ1_ACCOUNT_STATE, UNQ1_ACCOUNT_STATE))

ну собственно сам вопрос, а может можно оптимизатор научить смотреть еще на статистику PK,
ну и надо ли его этому учить ???

ps/ Я прекрасно понимаю что сам себе буратино и в моём случае надо было самому указывать
что индекс уникальный, однако могут быть случае когда индекс все-же не уникальный но
"дублирование" совсем мизерное
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38390863
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

статистика для ПК принимается упрощенной, т.е. стоимость индексного скана = 2 и стоимость чтения записи = 1. Так специально сделано, ибо не генерить кривые планы при устаревшей статистике.
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38390911
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrm7m,

статистика для ПК принимается упрощенной, т.е. стоимость индексного скана = 2 и стоимость чтения записи = 1. Так специально сделано, ибо не генерить кривые планы при устаревшей статистике.

Я так понимаю что и для уникального индекса аналогично???
...
Рейтинг: 0 / 0
Непонятки с оптимизатором 2.5.3
    #38390912
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

да, на самом деле выше я имел ввиду именно уникальный индекс
...
Рейтинг: 0 / 0
59 сообщений из 59, показаны все 3 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Непонятки с оптимизатором 2.5.3
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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