порядок оракула бежит ужасно медленно - PullRequest
2 голосов
/ 08 ноября 2011

Я делаю запрос, подобный этому, и для его завершения требуется 6 секунд:

select * 
from ( select aaa."ID" 
      from "aaa"  
      where aaa."DELETED" is null 
      order by aaa."CREATED" desc ) 
where rownum <= 15;

В моей таблице около 1,6 миллиона записей, и я попытался добавить отдельный индекс к удаленному столбцу и к созданному столбцу, я попытался добавить индекс, содержащий как созданные, так и удаленные столбцы, и я попытался создать один и тот же индекс в другом порядке. Кажется, ничто не поможет. Что я могу сделать, чтобы ускорить это?

Я не могу сильно изменить запрос, потому что он сгенерирован hibernate

Edit: даже без aaa."DELETED" is null запрос выполняется очень медленно.

Редактировать 2: Query plan

Редактировать 3: добавив мое определение индекса. я, честно говоря, не знаю, что означает большинство из этих чисел, я использую sqldeveloper для создания индексов. Даже не знал, что для каждого индекса есть так много опций конфигурации, я сейчас загляну в документацию.

CREATE INDEX "aaa"."aaa_CREATED_ASC" ON "aaa"."aaa"
  (
    "CREATED"
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;
CREATE INDEX "aaa"."aaa_CREATED_DESC" ON "aaa"."aaa"
  (
    "CREATED" DESC
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;

Ответы [ 2 ]

9 голосов
/ 08 ноября 2011

Вам необходимо понять, как Oracle обращается к записям в базе данных.Считывание индекса - это одно действие, чтение таблицы - это другое действие.Таким образом, для извлечения одной индексированной записи из таблицы требуется как минимум две операции чтения.

Ваш запрос использует три элемента информации:

  • столбец DELETED (критерий ограничения)
  • столбец CREATED (критерий сортировки)
  • идентификатор (набор результатов)

Oracle не индексирует значения NULL, поэтому индекс одного столбца для DELETED не будетпомочь тебе.Это полное сканирование таблицы, и не лучше, чем отсутствие индекса вообще.

Индекс для CREATED сам по себе лучше, потому что путь доступа станет следующим:

INDEX FULL SCAN DESCENDING

То есть, он начинается с самых последних дат в индексе и работает в обратном направлении.Однако для запроса все равно потребуется прочитать таблицу, чтобы найти идентификатор и значения DELETED.Это может быть много чтения таблицы, в зависимости от того, как часто DELETED имеет значение null.

Теперь составной индекс для (CREATED, DELETED) в этом порядке должен быть более полезным, потому что Oracle теперь будетиндексировать NULL в столбце DELETED.Oracle может использовать индекс, чтобы гарантировать, что он только ищет записи таблицы, чтобы получить значения ID.Это будет пятнадцать операций чтения таблицы.

Наконец, вы можете построить составной индекс на (CREATED, DELETED, ID) и обслуживать весь запрос из индекса.Это самый быстрый вариант.

Тогда вам просто нужно решить, оправдывают ли выигрыши в производительности издержки на поддержание индекса.Что бы это ни стоило, стоимость обслуживания составного индекса добавляет небольшую долю к стоимости обслуживания индекса из одного столбца.


Между прочим, ужасные запросы, подобные этому, являются одной из причин, почему плохая идея использовать логическое удаление.Физически удалите свои записи и используйте журнальные таблицы для извлечения исторического состояния вашей таблицы, когда вам это нужно.

0 голосов
/ 08 ноября 2011

попробуйте посмотреть здесь

http://www.dba -oracle.com / oracle_tips_null_idx.htm .

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

...