Prelude: У меня большой набор данных с несколькими сотнями тысяч записей, хранящихся в базе данных MySQL. Значительно упрощенный, каждая строка имеет поле даты и времени для хранения даты и времени, когда был сделан телефонный звонок, и целочисленное поле для хранения продолжительности вызова.
Сценарий: Я занят написанием интерполяционной функции в PHP, которая генерирует диапазон дат, разделенных предварительно рассчитанным интервалом. Каждая сгенерированная дата сохраняется в ассоциативном массиве с датой, используемой в качестве ключа, и каждое значение инициализируется равным 0. Затем сценарий запрашивает в базе данных список записей и пытается сопоставить запись даты-времени с ближайшей датой в пред. сгенерированный ассоциативный массив. Когда найдено самое близкое совпадение, оно просто добавляет длительность вызова к существующему значению массива с этим индексом.
Пример сгенерированного ассоциативного массива:
$array = array( "2011-01-01 09:00:00" => 0,
"2011-01-01 09:30:00" => 0,
"2011-01-01 10:00:00" => 0,
"2011-01-01 10:30:00" => 0,
"2011-01-01 11:00:00" => 0,
"2011-01-01 11:30:00" => 0,
"2011-01-01 12:00:00" => 0
)
В приведенном выше примере диапазон дат создается с интервалом в 30 минут.
Пример записей из базы данных MySQL:
+---------------------+----------+
| datetime | duration |
+---------------------+----------+
| 2011-01-01 09:02:26 | 1 |
| 2011-01-01 09:14:51 | 1 |
| 2011-01-01 10:40:33 | 549 |
| 2011-01-01 11:10:27 | 38 |
| 2011-01-01 11:31:50 | 82 |
+---------------------+----------+
Теперь необходимо сопоставить каждую из этих записей с ближайшим ключом даты и времени из предварительно сгенерированного массива, указанного выше, и к значению duration
, добавленному к существующему значению совпадения.
Проблема:
Достаточно просто построить два вложенных цикла for
, чтобы просмотреть записи из базы данных, а затем линейно прогнать ассоциативный массив, чтобы найти совпадение, но это крайне неэффективно и становится проблематичным для больших наборов данных (подумайте, сортировка пузырьков, вот что это будет примерно эквивалентно). Немного лучший подход заключается в линейном цикле записи записей из базы данных, а затем итерации по массиву в виде двоичного дерева, что, безусловно, намного более эффективно и возможно, поскольку оба массива отсортированы в хронологическом порядке.
Вопрос:
Есть ли более эффективный способ обработки сопоставления дат, чем, как я описал в приведенной выше проблеме?