Я пытаюсь найти несколько советов по оптимизации запроса, который я использую для извлечения большой группы данных.
Исходный код, над которым я работаю, прошел через большой набор пользователей и рассчитал диапазон дат для каждого из них. Затем он возьмет этот диапазон дат и запросит, сколько вопросов они ответили и сколько они получили правильно в этом диапазоне дат. Эти результаты были подсчитаны, и нам нужны именно те итоговые результаты.
То, что я уже сделал, чтобы ускорить это (потому что это занимало несколько минут), заключается в следующем: вместо того, чтобы запрашивать каждого пользователя по отдельности, скрипт теперь просто циклически просматривает каждого пользователя и вычисляет диапазон дат, который будет применим к ним все остальные аспекты запроса идентичны для каждого пользователя). Эти данные собираются в трехмерном массиве [startDate] [endDate] [userid], и один запрос создается для всех пользователей. Вот пример запроса, который получает вывод:
SELECT COUNT(uapl.id) AS numAnswered,
SUM(CASE WHEN (a.correct OR q.survey OR uapl.answersId IS NULL) THEN 1 ELSE 0 END) AS numCorrect
FROM usersAnswersProgramsLink uapl
JOIN questions q ON uapl.questionsId=q.id
LEFT JOIN answers a ON uapl.answersId=a.id
WHERE
programsId=123
AND
(
(
CAST(timestamp AS date) >= '2009-09-01'
AND CAST(timestamp AS date) <= '2009-09-21'
AND usercontextid in('123','234','345','465','567')
)
OR
(
CAST(timestamp AS date) >= '2009-09-10'
AND CAST(timestamp AS date) <= '2009-09-21'
AND usercontextid in('321','432','543')
)
OR
(
CAST(timestamp AS date) >= '2009-09-16'
AND CAST(timestamp AS date) <= '2009-09-21'
AND usercontextid in('987','876')
)
)
Это работает относительно хорошо при ускорении кода. В большинстве тестов, которые я выполняю, теперь это занимает от 20% до 10%. В моем худшем случае это всего лишь 50%, и я бы хотел улучшить это.
Этот наихудший случай случается, когда я сравниваю огромное количество идентификаторов пользователей (десять тысяч). Проблема сейчас в том, что больше нет необходимости оптимизировать алгоритм, из которого я извлек эти запросы. Это теперь проходит в миллисекундах. Этот запрос занимает много времени.
Так что это моя загадка. Я хотел бы ускорить это еще больше. Любые предложения будут приветствоваться. Пару информации, которая уместна здесь:
1) Между диапазонами дат и пользователями существует отношение 1 ко многим. ни один из этих идентификаторов пользователя не будет отображаться в нескольких диапазонах дат.
2) Конечным результатом, который мы ищем, являются именно эти подсчеты, но диапазоны дат необходимо рассчитывать для каждого пользователя, отсюда и массив идентификаторов для диапазона дат.
Одна вещь, которую я подумал ~ может ~ сделать это быстрее, - это создать временную таблицу со столбцом для диапазона дат и столбцом для идентификаторов пользователя. Затем перепишите этот запрос, используя JOIN для этой таблицы, а не помещая эти числа в сам запрос. Кто-нибудь знает, будет ли это работать?
Спасибо за любые предложения!