Timestamp вместо логических значений в БД


Один из самых простых, и в то же время эффективных трюков, которые я узнал недавно, связан с хранением логических значений в базе данных. Очень часто информация, для хранения которой мы должны использовать булевый столбец, тесно связана с информацией о том, когда это значение было изменено, даже если это не очевидно с первого взгляда:

  • если пользователь активен (только логическое значение), не хотим ли мы знать, когда он был активен в последний раз?
  • если продукт доступен на складе (только логическое значение), то в какой момент он стал доступен?
  • если подключение к сервису было успешным, в какой момент времени это подключение прошло?

Эта вторая часть вопроса, возникает в работе с информацией практически постоянно, и приводит к тому, что мы вынуждены создать дополнительную колонкy в БД, которая будет содержать эти данные. Но что если мы можем решить эту проблему изначально, не создавая дополнительных столблов?

Для этого достаточно использовать timestamp колонку вместо булевой колонки. В этом случае:

  • NULL заменяет False значение в колонке;
  • timestamp значение заменяет собой True, но дополнительно несёт информацию о времени этого изменения.

Этот метод настолько удобен и универсален, что его можно использовать практически в любом случае, где нужно использовать логические значения в столбце БД, даже если мы уверены, что информация о моменте изменения нас не будет интересовать (такое мнение часто оказывается ошибочным).

Теперь мы можем легко строить аналитику для данных на основе единственного столбца, отвечая сразу на сложные вопросы, вроде “когда этот продукт стал доступен на складе?”.

Правда в том, что ресурсы для корректной работы БД, как правило, в изобилии, и некоторая потеря эффективности в хранении данных не будет заметна. Можно представить себе пример, вроде использования логических значений в Clickhouse, который хорошо сжимает однородные данные именно на уровне столбца, и также хуже обрабатывает Nullable значения. Однако, на моей практике, даже в таком сценарии потери эффективности незначительны по сравнению с удобством от использования метода.

Второй отрицательный момент, не столько недостаток по сравнению с логическими значениями, сколько недостаток подхода в целом: мы знаем момент времени только для перехода с False на True, но не наоборот (с перезаписью на NULL эта информация теряется). Однако и здесь мы также имеем место для того, чтобы придумать алгоритм для решения этой проблемы. Например, можно изменять записи на NULL только по прошествии определенного времени (вопрос здесь меняется на “был ли сервер доступен последние 30 минут?”).

В любом случае, замена логических значений на время записи - это один из редких случаев, когда подход можно применять практически не задумываясь о негативных аспектах, и который уже несколько раз сэкономил мне время и усилия при аналитической работе с данными.