Я просто настроил систему регистрации, которая состоит из нескольких таблиц с одинаковым расположением.
Существует одна таблица для каждого источника данных.
Для просмотра журнала я хочу
- UNION все журнальные таблицы ,
- фильтровать их по аккаунту ,
- добавить псевдостолбец для идентификации источника,
- сортировать их по времени ,
- и ограничить их для нумерации страниц .
Все таблицы содержат поле с именем, zeitpunkt
которое является индексированным столбцом даты / времени.
Моя первая попытка была:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730)
ORDER BY zeit DESC LIMIT 10;
Оптимизатор не может использовать индексы здесь, потому что все строки из обеих таблиц возвращаются подзапросами и сортируются после UNION
.
Мой обходной путь был следующим:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
ORDER BY zeit DESC LIMIT 10;
Я ожидал, что механизм запросов будет использовать индексы здесь, так как оба подзапроса должны быть отсортированы и ограничены уже до UNION
, который затем объединяет и сортирует строки.
Я действительно думал, что это так, но выполнение EXPLAIN
запроса говорит мне, что подзапросы все еще ищут обе таблицы.
EXPLAINing
Сами подзапросы показывают мне желаемую оптимизацию, а UNIONing
их вместе - нет.
Я что-то пропустил?
Я знаю, что ORDER BY
предложения внутри UNION
подзапросов игнорируются без LIMIT
, но есть предел.
Изменить:
На самом деле, вероятно, также будут запросы безaccount_id
условия.
Таблицы уже существуют и заполнены данными. Могут быть изменения в макете в зависимости от источника, поэтому я хочу разделить их. Кроме того, клиенты журналирования используют разные учетные данные по причине.
Я должен держать своего рода слой между читателями журнала и фактическими таблицами.
Вот планы выполнения для всего запроса и первого подзапроса, а также детализация таблицы:
(account_id, zeitpunkt)
. У вас есть такой индекс? Вторым лучшим будет (я думаю) сингл(zeitpunkt)
- но эффективность, если он используется, зависит от того, как частоaccount_id=730
появляются строки с .UNION DISTINCT
? Там нет необходимости навязывать сортировку и различение, так как результаты будут разными для подзапросов из-за дополнительного столбца идентификации. ИспользованиеUNION ALL
.source
столбца? Таким образом, вы можете избежатьUNION
s и использовать индексы для всех ваших данных.UNION ALL
приводит к другому плану выполнения.Ответы:
Просто из любопытства, вы можете попробовать эту версию? Оптимизатор может обмануть использование тех же индексов, которые подзапросы будут использовать отдельно:
Я все еще думаю, что лучший индекс, который вы могли бы иметь, - это сложный
(account_id, zeitpunkt)
. Это дало бы 10 рядов быстро, и никаких трюков не понадобилось бы.источник
log entries / user
масштаб будет.account_id=?
, сохраните оба.SELECT * FROM
MySQL использовать индексы?(SELECT ...) AS a
, он пытается оценить и оптимизировать производную таблицу отдельно от других производных таблиц, а затем весь запрос.force index
даст вам лучшее решение.