Я работаю сопровождающим в устаревшей системе учета грузовых железнодорожных накладных на основе Java. Существует серьезная проблема с производительностью при получении списка накладных для отображения на их веб-сайте.
Я не могу опубликовать весь запрос, но вот некоторая статистика, чтобы дать общее представление:
- осталось 17 соединений
- в нем есть огромное предложение
where
с 5 группами ИЛИ, чтобы определить, разрешен ли пользователю доступ к записи из-за определенного отношения к записи (грузоотправитель, грузополучатель, перевозчик, плательщик, супервизор) и проверить разрешение пользователя для доступа к записям, относящимся к конкретной железнодорожной станции
- каждая группа OR имеет в среднем две
exists()
проверки с подзапросами на некоторые данные, относящиеся к записи, а также для проверки разрешения станции
- при расширении для удобства чтения запрос имеет длину около 200 строк
По сути, доступность каждой записи для текущего пользователя, вошедшего в систему, зависит от следующих факторов:
- компания пользователя
- компания перевозчика, грузополучателя, грузоотправителя, плательщика каждой конкретной накладной
- каждая накладная имеет несколько участков маршрута, и у каждого участка есть свой перевозчик и плательщик, поэтому требуются дополнительные условия контроля доступа, чтобы эти записи были видны пользователю
- каждая накладная и каждый участок маршрута имеют станции отправления и назначения, и пользователю разрешено просматривать запись только в том случае, если ему был предоставлен доступ к любой из этих станций (с использованием простой таблицы отношений).
В базе данных имеется около 2 миллионов записей накладной, и клиент жалуется, что загрузка страницы с 20 записями занимает слишком много времени.
К сожалению, невозможно оптимизировать окончательный запрос перед его передачей в СУБД (точнее, Oracle 11g), поскольку система имеет сложную архитектуру и инструмент ORM для домашнего пивоварения, а окончательный запрос собирается в как минимум три разных места, которые отвечают за сбор полей для выбора, сбор объединений, добавление критериев, выбранных в пользовательском интерфейсе, и, наконец, причину этого вопроса - фильтр, связанный с разрешениями.
Я бы не сказал, что последний запрос очень сложен; напротив, он прост по своей природе, но он просто огромен.
Я боюсь, что решения для кэширования не будут очень эффективными в этом случае, потому что данные изменяются очень часто, и кэш будет перезаписываться каждую минуту или около того. Кроме того, из-за индивидуальных прав доступа каждый пользователь должен иметь собственный кэш, который необходимо поддерживать.
Помимо обычных рекомендаций, касающихся индексов и максимально возможной оптимизации каждого подзапроса, существуют ли другие известные решения для фильтрации большого количества записей на основе сложных правил доступа?