delover
Advanced Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору AnGo Цитата: Тогда такая форма будет неполиткоррекна по отношению к пишущим справа налево и снизу вверх. | Возможно и я выражаю мысль не политкоректно. Сервер совершенно точно знает что индекс для последовательного чтения и индекс для поиска (например уникальный индекс при джойне) это разные индексы. Если для поиска уникального значения не важен порядок филдов в индексе, главное чтобы они были перечислены первыми. То для оптимизации ORDERBY вычисляется индекс для последовательного чтения! Сервер это отлично знает. Для своего примера я сделал смелое предположение что сервер FB найдёт оптимальный индекс для последовательного чтения. Не тут то было... Вот индекс: Код: CREATE INDEX TABLE1_IDX3 ON TABLE1 (PARENT_ID, GRADE_ID); | Вот выборка для которой этот индекс действительно оптимален: Код: select * from table1 t1 where t1.parent_id between 1 and 1 order by t4.parent_id, t4.grade_id | Вот автоматический план: Код: PLAN (T4 ORDER TABLE1_IDX3 INDEX (TABLE1_IDX2)) | Сервер в упор не увидел что TABLE1_IDX3 оптимален для последовательного чтения. По моей вводимой модели сервер должен знать что оптимальный индекс для последовательного чтения выделен пользователем. То есть подходит любой индекс начинающийся с условия пользователя. Если найден индекс подходящий пользователю + содержащий в себе условие ORDERBY, то он должен ОБЯЗАН ПО МОЕЙ МОДЕЛИ выбрать именно TABLE1_IDX3. +0 тут уже не канает, только через составление правильного плана можно заставить его использовать. ЗЫ Я бы написал свой препроцессор SQL который генерит такие планы, но это будет только для запросов на стороне клиента, а в хранимые процедуры я не могу засунуть свои знания запроса. А у сервера уже всё готово для этого - отсюда недовольство текущим положением. Рядом с ORDERBY не стояло условие последовательного чтения. Хотя для перехода от TABLE1_IDX2 до TABLE1_IDX3 теряются практически наносекунды, всё равно они теряются. Вот примерный код который нужен для состыковки индексов: Код: function TIndexList.IndexOf(RecNo: Integer): Integer; assembler; const FListPtr = 4; FCountPtr = 8; asm PUSH EDI PUSH ECX MOV EAX,Self MOV EDI,[EAX].FListPtr MOV ECX,[EAX].FCountPtr PUSH ECX MOV EAX,RecNo REPNE SCASD POP EAX JE @@1 OR EAX,-1 JMP @@2 @@1: SUB EAX,ECX DEC EAX @@2: POP ECX POP EDI end; | Мои тесты показывают, что эта операция на индексах очень быстрая (Индексы тут 4х байтные). На каждый RecNo выборки должна произойти подобная операция. Ну и зачем она Вам?.. Добавлено: Теперь о небывалом ускорении, которое увы не доступно потому что сервер вынужденно Вас игнорит. Пример: Код: select * from table1 t4 where t4.parent_id in (3,2,1,8) order by t4.grade_id | Все вполне справедливо: Код: PLAN (T4 ORDER TABLE1_IDX1 INDEX (TABLE1_IDX2, TABLE1_IDX2, TABLE1_IDX2, TABLE1_IDX2)) | Юзал индекс для каждого элемента по отдельности. Это всё вполне справедливо, но медленно. Если я напишу: Код: select * from table1 t4 on (t4.parent_id in (3,2,1,8)) order by t4.grade_id | То можно предположить что я это делаю сознательно. У элементов in есть максимальное и минимальное значение - это between 1 and 8. Индекс будет использован не 4 раза а всего 1 раз. Представим 20 элементов идущих сподряд в таблице с 5 миллионами записей. Это будет 20 раз использование 5и миллионного индекса. Я конечно могу представить пользователя который засунет туда in (3,2,1,4000000), но вет сервер не может быть виноват, что существуют глупые запросы? Но именно по этой причине Вам недоступно вполне реальное ускорение запроса уже не в сотни а в тысячи раз... | Всего записей: 1395 | Зарегистр. 25-06-2007 | Отправлено: 12:21 11-06-2012 | Исправлено: delover, 00:47 27-07-2012 |
|