Я - рабочий, которому поручено извлекать данные из очень большой таблицы. Я не администратор базы данных и не могу разделить его или изменить индексирование. Таблица содержит почти миллиард записей, не разбита на разделы и, вероятно, может быть проиндексирована «лучше». Мне нужно два поля, которые мы будем называть mod_date и obj_id (mod_date индексируется). РЕДАКТИРОВАТЬ: я также добавляю фильтр для «клиента», который я размыл на скриншоте плана объяснения.
Мои данные:
В группе из почти миллиарда строк у нас есть менее 10 000 значений obj_id для запроса в течение нескольких лет (некоторые из них могут даже быть NULL). Некоторые из <10k obj_ids - вероятно, от 1000 до 2500 - имеют более 10 миллионов значений mod_date каждое. Когда у obj_ids более нескольких миллионов значений mod_date, каждому obj_id требуется несколько минут для сканирования и сортировки с использованием MAX (mod_date). Полный набор результатов для запроса занимает более 12 часов, и никто не завершил его без какой-либо «проблемы» (заблокированный, отключенный ноутбук и т. Д.). Даже если мы получим первые 50 возвращенных строк, нам все равно нужно будет экспортировать их в Excel ... всего будет около 8000 строк с 2 столбцами, но мы никогда не сможем дойти до конца. </p>
Итак, вот упрощенный запрос, который я бы использовал, если бы он был маленькой таблицей:
select MAX(trunc(mod_date,'dd')) as last_modified_date, obj_id
from my_table
where client = 'client_name'
and obj_type_id = 12
group by obj_id;
Количество элементов 317917582, «Стоимость» 12783449
![explain plan](https://i.stack.imgur.com/QJXo0.png)
Выпуск:
Проблема заключается в скорости запроса с такой большой неразделенной таблицей, учитывая текущие индексы. Все остальные ответы, которые я видел о «самой последней дате», имеют тенденцию использовать MAX, возможно, в сочетании с FIRST_VALUE, которые, кажется, требуют полного сканирования всех строк, чтобы отсортировать их и затем определить, какая из них самая последняя.
Я надеюсь, что есть способ избежать этого, чтобы ускорить результаты. Похоже, что Oracle (я использую Oracle SQL developer) должен иметь возможность взять obj_id, найти самую последнюю строку mod_date, начиная с «сейчас» и работать в обратном направлении, и двигаться дальше, как только найдет какое-либо значение mod_date ... потому что это свидание. Есть ли способ сделать это?
Даже при такой большой таблице obj_ids, имеющей менее 10000 mod_dates, может очень быстро вернуть MAX (mod_date) (секунды или меньше). Проблема, с которой мы сталкиваемся, заключается в том, что obj_ids с наибольшим количеством mod_dates (более 10 миллионов) дольше всего сканирует и сортирует, когда они «должны» быть самыми быстрыми, если я смогу заставить Oracle начать сначала смотреть на самые последние… потому что это быстро найти последнюю дату и двигаться дальше!