Я пытаюсь представить журнал в таблице MySQL, где каждая строка журнала содержит строку system_id
, временную метку finish
, 20 обязательных столбцов данных, а затем 80 дополнительных столбцов. Часто все необязательные столбцы - это нули, которые мне не обязательно хранить. Когда есть значения, это обычно только для горстки из 80 столбцов. У меня нет возможности изменить формат журнала. Я загружаю тонны этих записей, до ~ 300M сейчас.
Изначально я представил это как две таблицы ...
log_data
, содержащие system_id
, finish
, и все обязательные столбцы с первичным ключом <system_id, finish>
.
log_data_extra
, содержащие system_id
, finish
и 80 дополнительных столбцов, первичный ключ <system_id, finish>
.
Обе таблицы разделены по дате finish
по месяцам. Этот путь является быстрым и легким для соединения двух таблиц, но тратит кучу дискового пространства и требует времени на вставку. Я подумал, что было бы лучше представлять только установленные значения из необязательных столбцов, а не нули. Итак, я воссоздал вторую таблицу:
Теперь log_data_extra
стало system_id
, finish
, optional_column_number
, optional_column_value
с первичным ключом <system_id, finish, optional_column_number>
. Это делает вставку очень быстрой, но присоединение к таблицам становится немного сложнее.
Мой запрос на соединение стал примерно таким:
select ld.system_id,
ld.finish,
sum((case when lde.optional_column_number = 0) then lde.optional_column_value else null end) as opt0,
sum((case when lde.optional_column_number = 1) then lde.optional_column_value else null end) as opt1,
sum((case when lde.optional_column_number = 2) then lde.optional_column_value else null end) as opt2,
... 80 times ...
from log_data ld
left join log_data_extra lde on ld.system_id = lde.system_id and ld.finish = lde.finish
group by ld.system_id, ld.finish
Проблема в том, что писать запросы, которые выглядят как этот. Я планировал сделать такой запрос в представлении, log_data_with_extra
, чтобы я мог присоединиться к представлению или запускать отчеты, подобные приведенным ниже:
select * from log_data_with_extra where finish between '2020-07-08' and '2020-07-09' and system_id = 'ABC123'
К сожалению, подобный запрос работает плохо. Основываясь на объяснении, похоже, что MySQL не может переместить ограничение диапазона на метку времени finish
внутри группы по представлению и должен сгруппировать все столбцы (в этой таблице в настоящее время около 80 тыс. Строк) до ограничение диапазона дат. Пока я перемещаю предложение where внутри группы на MySQL, фильтрация выполняется нормально, но только не, если я пытаюсь использовать представление.
Могу ли я что-нибудь сделать, чтобы упростить эту ситуацию и сделать проще ли присоединиться ко всем 80 из этих необязательных значений в паре system_id
, finish
? Или мне нужно выписывать все 80 из этих фраз sum (case ()) каждый раз, когда у меня есть запрос, в котором я хочу ссылаться на них таким образом?
Спасибо!