Оптимальный способ хранения значений даты и времени в базе данных SQLite (Delphi) - PullRequest
8 голосов
/ 21 января 2010

Я буду хранить значения даты и времени в базе данных SQLite (используя Delphi и библиотеку DISqlite). Природа БД такова, что ее никогда не нужно будет передавать между компьютерами или системами, поэтому совместимость не является ограничением. Вместо этого я концентрируюсь на скорости чтения. Поле datetime будет проиндексировано, и я буду много его искать, а также последовательно читаю тысячи значений datetime.

Поскольку SQLite не имеет явного типа данных для значений даты и времени, существует несколько параметров:

  • используйте тип данных REAL и сохраняйте значения Delphi TDateTime напрямую: самый быстрый, без преобразования из строки при загрузке; невозможно отладить даты с помощью менеджера БД, такого как SQLiteSpy, так как даты не будут читаться человеком. Невозможно использовать функции даты SQLite (?)

  • использовать простой формат строки, например, YYYYMMDDHHNNSS: преобразование требуется, но относительно просто на ЦП (не нужно сканировать разделители), данные удобочитаемы. Все еще не может использовать функции даты SQLite.

  • сделать что-нибудь еще. Что рекомендуется сделать?

Я прочитал http://www.sqlite.org/lang_datefunc.html, но нет никакого упоминания о том, какой тип данных использовать, и, не будучи формально обученным в программировании, я не совсем обращаю внимание на юлианские даты. Почему дополнительная конверсия? Я буду много читать в этих значениях, поэтому любые дополнительные преобразования между строками и TDateTime увеличивают стоимость.

Ответы [ 5 ]

8 голосов
/ 21 января 2010

Вы можете использовать один из поддерживаемых форматов строк SQLite, например. YYYY-MM-DD HH:MM:SS.SSS.

Это было бы так же просто, как и YYYYMMDDHHNNSS - вам все равно не нужно сканировать разделители, поскольку все числа имеют фиксированную длину - и вы получите поддержку функции даты SQLite.

Если вам нужна поддержка функции даты в SQLite, я бы выбрал этот метод.

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

5 голосов
/ 21 января 2010

Одним из компромиссов было бы придерживаться РЕАЛЬНЫХ значений, но сохранять их как юлианские даты, используя Delphi DateTimeToJulianDate. Таким образом, они остаются быстрыми для чтения, при конвейере теряется мало производительности, и они все еще находятся в формате, который имеет смысл вне Delphi.

2 голосов
/ 21 января 2010

Для этого я обычно использую тип данных Integer и сохраняю значение метки времени Unix (например, # секунд с 1-1-2000). Вычисление этого t / из TDateTime равно умножению / погружению с / на 86400 и добавлению константы для «с тех пор».

Если вам нужна большая точность, вы можете использовать DateTime в качестве FILETIME (например, int64) с шагом 100 нс. Для этого в SysUtils есть процедуры преобразования, и ваша временная метка хранится в UTC.

0 голосов
/ 10 октября 2013

Я не знаю, применим ли этот ответ к библиотеке DISqlite, но ...
Ниже приведен код, который иллюстрирует, что работает для меня как с использованием Delphi 2010, так и оболочки SQLite3 Тима Андерсона.

SQL для создания поля:

  sSQL :=  'CREATE TABLE [someTable] (' +
            '  [somefield1] VARCHAR(12),' +
            '  [somefield2] VARCHAR(12),' +
            '  [myDateTime] DATETIME );';

SQL для заполнения поля:

 sSQL := 'INSERT INTO someTable(somefield1, somefield2, myDateTime)' + 
         '  VALUES ( "baloney1", "baloney2","' + FloatToStr(Now) + '");';

Пример получения данных из поля:

var
sDBFilePathString: string;
sl3tbl: TSqliteTable;
fsldb : TSQLiteDatabase;
FromdbDTField : TDateTime;

begin
   ...
   ... 
    fsldb := TSQLiteDatabase.Create(sDBFilePathString); 
    sl3tbl := fsldb.GetTable('SELECT * FROM someTable');
    FromdbDateTime := StrToFloat(sl3tbl.FieldAsString(sl3tbl.FieldIndex['myDateTime']));
    Showmessage('DT: ' + DateTimeToStr(FromdbDTField));
end;

Результат:

**DT: 10/10/2013 1:09:53 AM**

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

0 голосов
/ 22 января 2010

Если на уровне базы данных вас интересует только читаемый формат, вы можете сохранить два отдельных поля, например:

DELPHI_DATE REAL (DOUBLE, если возможно, но я не знаю SQLite), проиндексировано. Все ваши программные запросы и сравнения должны использовать это поле.

HUMAN_READABLE_DATE Varchar (23) в формате «ГГГГ-ММ-ДД ЧЧ: ММ: СС.ССС». Может быть проиндексирован (если это действительно необходимо). Большинство запросов на ввод данных человеком должно включать это поле, и вы можете использовать (как говорят другие) функции даты SQLite.

У него есть некоторые недостатки:

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

Если это подходит для ваших конкретных потребностей, до вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...