May. 23rd, 2017

crower: (Default)

С оптимизацией получился облом.

Напомню, что была попытка соптимизировать запрос с select ... where date(field) in (...) group by .... Я в курсе, что конструкция field in (...) сама по себе дорогая, но вполне приемлема, если потеря скорости незначительна, а альтернатива может оказаться ещё дороже.

В моей ситуации потеря скорости оказалась слишком велика, чтобы её игнорировать.

Попробовал другое "дешёвое" решение — внедрить ограничение диапазона, где код where date(field)≥{min_time} and date(field)<{max_time} призван был сократить первоначальную выборку, и уже после этого работал бы var in (...). Нужно было планчик составить, но лениво. А потом оказалось что и var in лишний. С выборкой нужных дат в самом скрипте всё оказалась гораздо быстрее. И поначалу всё заработало как надо. И дело даже не в кешировании. Потому как регулярно, раз в час поступают новые данные.

Эффект был кажущимся из-за того, что на момент тестирования дат было не так много и group by на все эти даты не сильно тормозил. Но наступление события "С", ради которого весь этот сыр-бор, задержалось. И получилось что между первой и последней датой времени прошло настолько много, что быстродействие от экономии на отказе от var in полностью пожралось group by. Долгим и бессмысленным.

Ещё бы:

  • 4 таблицы: 1.2млн, 1.3млн, 26млн и 27млн записей.
  • интересующие данные (без уточнения по дате) составляют 64К, 10К, 130К и 20К записей.
  • в таблицах сидит timestamp, а выборку и результат нужно делать от функции по нему. Хоть через substr, хоть по date.

Можно было плюнуть и вернуться к старой схеме, но "мы не привыкли отступать"© и это оскорбляет эстетическое чувство.

Поэтому пришлось делать красиво и по-полной схеме. При обращении к странице, скрипт запрашивает данные, уже сгруппированные по дате и лежащие в специальной дочерней таблице. Если на определённую дату данных нет, то запрашиваются данные в родительской таблице. Если они оказываются полными за указанную дату (24 часа, 1440 минут или 86400 минут), то они вставляются в дочернюю таблицу и в следующий раз будут извлекаться оттуда. Считать их заново будет не нужно. Операция сия была необходима для одного определённого объекта, так что пухнуть дочерние таблицы не будут. При периодическом опросе данные за прошедшие дни обстчитываются постепенно, и только за текущий - постойнно. В результате подтормаживание составляет при пересчёте прошедших суток считанные доли секунды, а за текущую дату - даже не заметно. Всё-таки выборка по timestamp ≥ {time} and (timestamp < {time} + INTERVAL 1 DAY) гораздо быстрее, чем упоминавшиеся ранее конструкции. Да и group by нужно будет убрать, т.к. алгоритм и ткак каждый раз выдёргивает по одной строке.

Зато теперь всё классно. :)

Profile

crower: (Default)
crower

February 2018

S M T W T F S
    123
45678910
11121314151617
181920212223 24
25262728   

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 24th, 2025 04:07 pm
Powered by Dreamwidth Studios