2010-01-21 58 views
8

Tôi sẽ lưu trữ giá trị datetime trong cơ sở dữ liệu SQLite (sử dụng thư viện Delphi và DISqlite). Bản chất của db là như vậy mà nó sẽ không bao giờ cần phải được chuyển giao giữa các máy tính hoặc các hệ thống, do đó khả năng tương tác không phải là một hạn chế. Thay vào đó, tiêu điểm của tôi là tốc độ đọc. Trường datetime sẽ được lập chỉ mục và tôi sẽ tìm kiếm trên nó rất nhiều, cũng như đọc hàng ngàn giá trị datetime theo thứ tự.Cách tối ưu để lưu trữ giá trị datetime trong cơ sở dữ liệu SQLite (Delphi)

Kể từ SQLite không có một kiểu dữ liệu rõ ràng cho các giá trị datetime, có một số lựa chọn:

  • sử dụng kiểu dữ liệu REAL và giá trị TDateTime cửa hàng của Delphi trực tiếp: nhanh nhất, không có chuyển đổi từ chuỗi trên tải; không thể gỡ lỗi ngày bằng cách sử dụng trình quản lý db chẳng hạn như SQLiteSpy, vì ngày tháng sẽ không thể đọc được bằng con người. Không thể sử dụng các hàm ngày SQLite (?)

  • sử dụng định dạng chuỗi đơn giản, ví dụ: YYYYMMDDHHNNSS: chuyển đổi là cần thiết nhưng tương đối dễ dàng trên CPU (không cần phải quét các dấu phân cách), dữ liệu có thể đọc được. Vẫn không thể sử dụng các hàm ngày SQLite.

  • làm điều gì đó khác. Bạn nên làm gì?

Tôi đã đọc http://www.sqlite.org/lang_datefunc.html nhưng không có đề cập đến những gì kiểu dữ liệu để sử dụng, và không được chính thức theo học lập trình, tôi không khá grok tập trung vào Julian ngày. Tại sao chuyển đổi bổ sung? Tôi sẽ đọc các giá trị này rất nhiều, vì vậy bất kỳ chuyển đổi bổ sung nào giữa các chuỗi và TDateTime đều bổ sung một chi phí đáng kể.

+0

Tôi cũng đã thấy http://stackoverflow.com/questions/1933720/how-do-i-insert-datetime-value-into-a-sqlite-database nhưng nó không trả lời câu hỏi của tôi về những gì cách tối ưu là, hoặc là có một lý do thực sự thuyết phục để thích định dạng chuỗi ISO (và các chuyển đổi liên quan) hơn chèn trực tiếp các giá trị TDateTime của Delphi. –

Trả lời

8

Bạn có thể sử dụng một trong các định dạng chuỗi được hỗ trợ SQLite, ví dụ: YYYY-MM-DD HH:MM:SS.SSS.

Nó sẽ dễ dàng như YYYYMMDDHHNNSS - bạn vẫn không cần phải quét dấu phân tách vì tất cả các số đều có độ dài cố định - và bạn sẽ nhận được hỗ trợ chức năng ngày SQLite.

Nếu bạn cần hỗ trợ chức năng ngày SQLite, tôi sẽ đi với phương pháp đó.

Nếu không, tôi khuyên bạn nên sử dụng các giá trị REAL. Bạn vẫn có thể so sánh chúng với nhau (số cao hơn là sau này trong thời gian), và xem xét ngày và thời gian riêng biệt (trước và sau dấu thập phân tương ứng) mà không cần chuyển đổi sang TDateTime.

+0

Tôi đã sử dụng giải pháp ASCII này rất nhiều, với CSV và các cơ sở dữ liệu khác, và những gì tôi muốn làm. Hơn nữa các hàm ngày SQLite hoạt động. Thắng thắng thắng. –

5

Một thỏa hiệp sẽ được gắn với giá trị REAL, nhưng lưu trữ chúng dưới dạng ngày tháng julian bằng cách sử dụng DateTimeToJulianDate của Delphi. Bằng cách đó họ vẫn còn nhanh chóng để đọc, có ít hiệu suất bị mất trong hội tụ, và họ vẫn còn trong một định dạng có ý nghĩa bên ngoài của Delphi.

+0

Tôi đã sử dụng giá trị REAL trước đây, một nhược điểm là các giá trị trong DB không ** có thể đọc được **, và điều này là bất tiện khi gỡ lỗi/phân tích bằng cách sử dụng công cụ SQL. –

2

Đối với điều này, tôi thường sử dụng kiểu dữ liệu nguyên và lưu trữ giá trị dấu thời gian Unix giống nhau (ví dụ: eq # giây kể từ 1-1-2000 chẳng hạn). Tính toán này t/từ một TDateTime là bằng cách nhân/lặn với/bởi 86400 và thêm một hằng số cho 'kể từ'.

Nếu bạn cần độ chính xác cao hơn Bạn có thể sử dụng DateTime làm FILETIME (ví dụ: int64) có số gia số 100 ns. Có thói quen chuyển đổi trong SysUtils cho rằng và dấu thời gian của bạn được lưu trữ trong UTC.

0

Nếu bạn lo ngại chỉ có thể đọc được định dạng con người ở cấp cơ sở dữ liệu, bạn có thể lưu trữ hai lĩnh vực riêng biệt, ví dụ:

DELPHI_DATE REAL (DOUBLE, nếu có thể, nhưng tôi không biết SQLite), được lập chỉ mục . Tất cả các truy vấn và so sánh có lập trình của bạn nên sử dụng trường này.

HUMAN_READABLE_DATE Varchar (23) với định dạng 'YYYY-MM-DD HH: MM: SS.SSS'. Có thể lập chỉ mục (nếu thực sự cần thiết). Đa số các truy vấn đầu vào của con người nên bao gồm trường này và bạn có thể sử dụng (như đã nói bởi những người khác) các hàm ngày SQLite.

Nó có một số nhược điểm: tiêu thụ

  • Space tại cơ sở dữ liệu và lưu lượng mạng phát triển,
  • hoạt động chèn sẽ mất nhiều hơn một chút vì chuyển đổi cần thiết,
  • không đồng bộ tự động giữa các giá trị nếu được cập nhật bên ngoài của bạn chương trình

Nếu phù hợp với nhu cầu cụ thể của bạn, tùy thuộc vào bạn.

0

Tôi không biết câu trả lời này có thể áp dụng cho thư viện DISqlite hay không ...
Dưới đây là một số mã minh họa những gì phù hợp với tôi bằng cách sử dụng cả trình bao SQLite3 của Delphi 2010 và Tim Anderson.

SQL để tạo ra lĩnh vực:

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

SQL để cư lĩnh vực:

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

Ví dụ về lấy dữ liệu từ lĩnh vực:

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; 

Kết quả:

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

Giống như tôi đã đề cập trên dòng đầu tiên - Tôi không biết điều này có hoạt động với thư viện DISqlite hay không nhưng nếu nó thực hiện cách xử lý khá rõ ràng. Tôi để nó cho bạn để làm cho mọi thứ đẹp hơn hoặc thanh lịch hơn.

Các vấn đề liên quan