Открыть сервисСервис

Тип данных DATETIME2

DATETIME2 — это тип данных для хранения даты и времени в системах управления базами данных (СУБД), в первую очередь в Microsoft SQL Server. Он является эволюционным развитием типа DATETIME и предназначен для обеспечения бо́льшей точности, расширенного диапазона дат и меньшего объёма занимаемой памяти.

Общая характеристика

Тип DATETIME2 был введён в Microsoft SQL Server 2008 года (версия 10.0). Он позволяет хранить значения от 0001-01-01 по 9999-12-31 (по григорианскому календарю) с точностью до 100 наносекунд. В отличие от устаревшего типа DATETIME (который имеет точность около 3,33 миллисекунды и диапазон только с 1753 года), DATETIME2 не зависит от календарной системы, используемой в SQL Server (например, для юлианского календаря). Размер хранимого значения зависит от указанной точности: от 6 байт (при точности меньше 100 наносекунд) до 8 байт (при максимальной точности). Для сравнения, старый тип DATETIME всегда занимает 8 байт, независимо от точности.

Синтаксис и параметр точности

В SQL Server тип данных объявляется как DATETIME2[(fractional seconds precision)], где fractional seconds precision — это число от 0 до 7, определяющее количество знаков после запятой для секунд. Значение по умолчанию — 7 (100 наносекунд). Например:

  • DATETIME2(0) — точность до секунд (без долей секунд).
  • DATETIME2(3) — точность до миллисекунд.
  • DATETIME2(7) — максимальная точность (100 наносекунд).

Чем меньше число, тем меньше объём памяти: таблица соответствия:

  • 0–2: 6 байт
  • 3–4: 7 байт
  • 5–7: 8 байт

Это свойство позволяет оптимизировать хранение, если высокая точность не требуется.

Формат представления

Значение DATETIME2 хранится в виде двух целых чисел: количество дней от базовой даты (0001-01-01) и количество единиц времени (100-наносекундных тактов) после полуночи. При выводе (например, в SSMS) обычно отображается в строковом формате YYYY-MM-DD hh:mm:ss[.fffffff]. Однако стоит отметить, что на уровне данных нет фиксированного формата — интерпретация зависит от клиентского приложения. Стандартный литерал для вставки: '2025-01-15 14:30:00.1234567'.

Сравнение с другими типами даты и времени

DATETIME (устаревший)

  • Диапазон: 1753-01-01 — 9999-12-31
  • Точность: ~3,33 мс (округление до 1/300 секунды)
  • Размер: 8 байт (всегда)
  • Не поддерживает юлианский календарь и произвольную точность.

SMALLDATETIME

  • Диапазон: 1900-01-01 — 2079-06-06
  • Точность: 1 минута
  • Размер: 4 байта
  • Подходит для систем, где важна экономия памяти и не нужны секунды.

TIME

  • Хранит только время (без даты).
  • Диапазон: 00:00:00.0000000 — 23:59:59.9999999
  • Точность: до 100 нс (зависит от параметра).
  • Размер: от 3 до 5 байт.

DATE

  • Хранит только дату (без времени).
  • Диапазон: 0001-01-01 — 9999-12-31
  • Размер: 3 байта.
  • Не зависит от часового пояса.

DATETIMEOFFSET

  • Хранит дату, время и смещение относительно UTC (часовой пояс).
  • Диапазон: 0001-01-01 — 9999-12-31
  • Точность: до 100 нс
  • Размер: 10 байт (при точности 7)

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

Производительность и индексы

DATETIME2 поддерживает все стандартные операции сравнения, сортировки и арифметики (например, DATEDIFF, DATEADD). Благодаря компактному представлению, операции с ним часто выполняются быстрее, чем с DATETIME, особенно при наличии индексов. Индексы по столбцам типа DATETIME2 могут быть кластеризованными и некластеризованными. Однако стоит учитывать, что при сохранении значения с дробными долями секунды (например, 1234567 для 7-й точности) эти доли участвуют в сортировке, что может влиять на порядок строк.

Поддержка временных таблиц и темпоральных таблиц

В SQL Server 2016 (версия 13.0) была введена поддержка системно-версионируемых темпоральных таблиц (Temporal Tables). Для столбцов периода (period columns) обязательно используются типы DATETIME2 (или DATETIMEOFFSET). Это связано с тем, что для корректной работы темпоральных таблиц требуется высокая точность (обычно 7 знаков) и расширенный диапазон. Темпоральные таблицы автоматически записывают время начала и окончания действия каждой версии строки, и здесь небольшая погрешность в 100 нс является допустимым компромиссом.

Работа из прикладных языков

При передаче значений DATETIME2 через драйверы баз данных (например, ODBC, JDBC, ADO.NET) необходимо учитывать точность. Многие языки программирования (C#, Java, Python) имеют собственные типы с дробными секундами (например, datetime2 в .NET). При сериализации в JSON или XML часто требуется явное указание формата. Например, в REST API на .NET Core по умолчанию используется формат ISO 8601: 2025-01-15T14:30:00.1234567. Однако старые библиотеки могут усекать дробные доли секунды до 3 знаков.

Преимущества и недостатки

Преимущества:

  • Широкий диапазон дат (с 1 года нашей эры).
  • Высокая точность (до 100 нс).
  • Компактное хранение (меньше места при низкой точности).
  • Стандарт ISO 8601 совместим (с точностью до 7 знаков).
  • Не зависит от устаревших календарных настроек.

Недостатки:

  • Не хранит информацию о часовом поясе (для этого нужен DATETIMEOFFSET).
  • В старых версиях SQL Server (до 2008) не поддерживался.
  • При конвертации из строки с 8+ знаками после запятой происходит округление.
  • Не все инструменты BI и ETL корректно обрабатывают 7-значную точность (например, Excel может потерять микросекунды).

Практические рекомендации

Для новых проектов на Microsoft SQL Server рекомендуется использовать DATETIME2 вместо DATETIME, если не требуется совместимость с очень старым кодом. При работе с временными рядами, журналами аудита, финансовыми транзакциями (где критична миллисекундная точность) стоит выбирать DATETIME2(3) (миллисекунды) или DATETIME2(7) (наносекунды). Для задач, где дата и время берутся с точностью до минуты (например, расписание встреч), можно использовать DATETIME2(0) для экономии памяти (6 байт вместо 8).

В других СУБД аналогичные типы могут называться по-другому. Например, в PostgreSQL это TIMESTAMP (без часового пояса), в Oracle — TIMESTAMP(9), в MySQL — DATETIME(6). Все они близки по функциональности, но имеют свои особенности работы с дробными секундами и диапазонами.

Известные проблемы

  • При вставке значения с дробной частью, превышающей указанную точность, происходит округление до ближайшего значения (например, DATETIME2(3) с '2025-01-15 12:00:00.1234567' станет '2025-01-15 12:00:00.123').
  • В некоторых версиях SQL Server 2008–2012 наблюдались проблемы с производительностью при сортировке миллиардов строк с типом DATETIME2 из-за особенностей хранения.
  • Использование DATETIME2 в качестве ключа кластеризованного индекса может приводить к фрагментации, если значения вставляются не последовательно (например, из разных источников с большими скачками дат).

Будущее

С появлением более современных типов данных (например, TIME, DATE, DATETIMEOFFSET) и развитием облачных баз данных (Azure SQL Database) DATETIME2 остаётся стандартным выбором для большинства OLTP-приложений. Компания Microsoft не анонсировала планов по замене этого типа в ближайшей перспективе, однако рекомендуется отслеживать новые версии SQL Server для возможных оптимизаций хранения и производительности.

Источники

  • Microsoft Docs: «datetime2 (Transact-SQL)»
  • Книга «Inside Microsoft SQL Server 2008: T-SQL Querying» (Itzik Ben-Gan)
  • Заметки из документации к SQL Server 2022
  • Обсуждения на Stack Overflow по производительности типов даты и времени
Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru