Я пишу запрос для очень конкретного отчета, который содержит переменное количество столбцов, основанных на определенных отношениях элемента. Я открыт для предложений о том, как изменить запрос, если это необходимо, но я не думаю, что это может быть. Я бы предпочел оставить это как отдельный запрос, а не запускать его в цикле. Таблица, в которой выполняется поиск, содержит около 4 миллионов записей и не может быть заархивирована.
Я хотел бы знать, почему индекс DATEADD не используется в подзапросе, хотя он используется во внешнем запросе, который находится в той же таблице. Мне известно, что функции в поле не позволяют индексировать MySQL, но это касается только элемента, а не того, с чем вы сравниваете его.
Результатом отчета является число для каждого конкретного элемента (подзапроса) для каждой даты в диапазоне, где что-то имело место. Диапазон дат генерируется динамически. Подзапросы должны возвращать результаты за один день
Мы используем MySQL версии 5.0.77, которую мы не можем изменить, поскольку она управляется нашим хостинг-провайдером.
Вот запрос:
SELECT DATE_FORMAT(DATEADD, '%d/%m/%y') AS DATEADD,
(SELECT COUNT(ID)
FROM ATABLE AS
WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 132
AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
AS '132',
(SELECT COUNT(ID)
FROM ATABLE AS
WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 149
AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
AS '149'
FROM ATABLE AS V
WHERE 1 = 1 AND COMPID = 132
AND (V.DATEADD >= "2010-09-01 00:00:00"
AND V.DATEADD <= "2010-10-26 23:59:59")
AND 1 = 1
AND ELEMNAME = 'ANELEMENT'
GROUP BY DATE_FORMAT(DATEADD, '%Y-%m-%d')
Количество выполнений подзапроса зависит от количества ссылок, которые имеет этот элемент, и определяется при построении запроса.
Мы попробовали:
заменив их на
"VT.DATEADD <= DATE(V.DATEADD) and VT.DATEADD <= DATE(V.DATEADD) +1"
однако это тоже не работает, изменив его на
"VT.DATEADD = DATE(V.DATEADD)"
использует индекс, однако не возвращает правильное количество строк, поскольку DATEADD - это дата и время. Если мы изменим его на:
"VT.DATEADD >= "2010-09-01" AND VT.DATEADD <= "2010-09-02"
Вывод из Объяснение
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
| 1 | PRIMARY | V | range | DATEADD,COMPID,ELEMNAME | DATEADD | 8 | NULL | 1386 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | VT | ref | COMPID,ELEMNAME | ELEMNAME | 103 | const | 44277 | Using where |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
При использовании USE INDEX или FORCE INDEX (когда он доступен, но не используется) используется клавиша NULL
, не исправляя это, запрос выполняется невероятно медленно, даже в крошечном диапазоне дат, и блокирует базу данных.