Лучший способ заполнить пробелы во временном ряду в запросе Mysql - PullRequest
0 голосов
/ 14 ноября 2011

Мне нужно заполнить пробелы во временном ряду набора результатов запроса mysql.Я нахожусь в процессе тестирования варианта выполнения внешнего соединения с вспомогательной таблицей, которая содержит все точки данных временного ряда (как указано в этой теме: Как заполнить пробелы в датах в MySQL? ).

Проблема, с которой я сталкиваюсь, заключается в том, что добавление этого объединения значительно увеличивает время ответа на запрос (оно увеличивается с 1 до 90 секунд).

Вот исходный запрос:

select date_format(fact_data7.date_collected,'%Y-%m') as date_col
   , date_format(fact_data7.date_collected,'%d-%H:%i:%s') as time_col
   , fact_data7.batch_id,fact_data7.value as fdvalue,entities.ticker as ticker
   , date_format(fact_data7.date_collected,'%Y-%m-%d') as date_col2
   , date_format(fact_data7.date_collected,'%Y') as year 
from fact_data7  
JOIN entities on fact_data7.entity_id=entities.id  
where (1=1)
  AND ((entities.id= 963
      AND fact_data7.metric_id=1
      ))
  AND date_format(fact_data7.date_collected,'%Y-%m') > '2008-01-01'
order by date_col asc

, а вот запрос с добавленным внешним соединением к вспомогательной таблице (month_fill):

select date_format(month_fill.date,'%Y-%m') as date_col
    , date_format(fact_data7.date_collected,'%d-%H:%i:%s') as time_col
    , fact_data7.batch_id,fact_data7.value as fdvalue
    , entities.ticker as ticker
    , date_format(fact_data7.date_collected,'%Y-%m-%d') as date_col2
    , date_format(fact_data7.date_collected,'%Y') as year 
from fact_data7
JOIN entities
  on fact_data7.entity_id=entities.id  
RIGHT OUTER JOIN month_fill
   on date_format(fact_data7.date_collected,'%Y-%m') =  date_format(month_fill.date,'%Y-%m')  
where (1=1)
  AND (
      (entities.id= 963 AND fact_data7.metric_id=1)
      OR (entities.id is null and fact_data7.metric_id is null)
      )
  AND date_format(month_fill.date,'%Y-%m') > '2008-01-01'
order by date_col asc

Можно ли реструктурироватьзапрос для повышения производительности есть ли альтернативное решение для достижения того, что я ищу?

Обновление 11/15:

Вот вывод EXPLAIN для 1-го запроса:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  entities    const   PRIMARY     PRIMARY     4   const   1   Using filesort
1   SIMPLE  fact_data7  ALL     NULL    NULL    NULL    NULL    230636  Using where

Вот вывод EXPLAIN для второго запроса:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  month_fill  index   NULL    date    8   NULL    204     Using where; Using index; Using temporary; Using filesort
1   SIMPLE  fact_data7  ALL     NULL    NULL    NULL    NULL    230636  Using where
1   SIMPLE  entities    eq_ref  PRIMARY     PRIMARY     4   findata.fact_data7.entity_id    1   Using where

Ответы [ 2 ]

0 голосов
/ 15 ноября 2011

Я думаю, стоит попробовать переписать where, чтобы не использовать date_format(date_collected). Вы говорите, что у вас есть индекс для этого поля, но он никогда не используется (поле является аргументом функции, MySQL не поддерживает индексы на основе функций)

0 голосов
/ 14 ноября 2011

Даже не смотря на рефакторинг запроса, я бы начал с добавления индекса по столбцам даты fact_data7.data_collected и month_fill.date.Запрашиваемый вами диапазонный диапазон «>» замедляет процесс, и добавление индекса теоретически должно повысить производительность, но вам нужно достаточно записей, иначе управление индексом будет только замедляться из-за обработки, связанной с управлением индексом.

См. Эту документацию по mysql http://dev.mysql.com/doc/refman/5.0/en/optimization-indexes.html

Я не уверен, чего именно вы пытаетесь достичь, но вы можете попытаться сделать это, используя функцию ifnull(value1,value2) mysql.Ваш запрос может выглядеть примерно так:

select ifnull(date_format(fact_data7.date_collected,'%Y-%m'),date_format(month_fill.date,'%Y-%m')) as date_col, 
date_format(fact_data7.date_collected,'%d-%H:%i:%s') as time_col, 
fact_data7.batch_id,
fact_data7.value as fdvalue,
entities.ticker as ticker,
date_format(fact_data7.date_collected,'%Y-%m-%d') as date_col2 ,
date_format(fact_data7.date_collected,'%Y') as year 
from fact_data7 , month_fill
JOIN entities on fact_data7.entity_id=entities.id  
where ((entities.id= 963 AND fact_data7.metric_id=1) OR (entities.id is null and fact_data7.metric_id is null))
and date_format(fact_data7.date_collected,'%Y-%m') =  date_format(month_fill.date,'%Y-%m') --you will need a condition similar to this depends on the data
AND date_format(fact_data7.date_collected,'%Y-%m')>'2008-01-01'
order by date_col asc
...