Ngày tháng được thể hiện như thế nào trong mysql?

Bất cứ khi nào bạn cần lưu dữ liệu datetime, một câu hỏi đặt ra là nên sử dụng loại MySQL nào. Bạn có sử dụng loại MySQL DATE gốc hoặc sử dụng trường INT để lưu trữ thông tin ngày và giờ dưới dạng số đơn giản không?

Trong bài viết này, tôi sẽ giải thích các tùy chọn gốc của MySQL và cung cấp cho bạn bảng so sánh các kiểu dữ liệu phổ biến nhất. Chúng tôi cũng sẽ đánh giá một số truy vấn điển hình và đưa ra một số kết luận về việc sử dụng kiểu dữ liệu nào trong một tình huống nhất định

Kiểu dữ liệu thời gian của MySQL gốc

Dữ liệu ngày giờ đại diện cho một thời điểm. Đây có thể là mục nhật ký, dấu thời gian Internet of Things, dữ liệu sự kiện lịch, v.v. MySQL có hai kiểu gốc cho phép chúng tôi lưu thông tin này trong một trường duy nhất. Ngày giờ và Dấu thời gian. Đây là những gì tài liệu MySQL nói về các kiểu dữ liệu này

Loại DATETIME được sử dụng cho các giá trị chứa cả phần ngày và giờ. MySQL truy xuất và hiển thị các giá trị DATETIME trong 'YYYY-MM-DD HH. MM. định dạng SS

Kiểu dữ liệu DẤU THỜI GIAN được sử dụng cho các giá trị chứa cả phần ngày và giờ

Giá trị DATETIME hoặc TIMESTAMP có thể bao gồm phần phân số giây ở cuối với độ chính xác lên đến micro giây (6 chữ số)

Các kiểu dữ liệu TIMESTAMP và DATETIME cung cấp tự động khởi tạo và cập nhật đến ngày và giờ hiện tại bằng cách sử dụng các mệnh đề DEFAULT CURRENT_TIMESTAMP và ON UPDATE CURRENT_TIMESTAMP trong định nghĩa cột

Vì vậy, như một ví dụ

CREATE TABLE `datetime_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;

Bên cạnh các biểu diễn ngày giờ riêng, còn có một cách tiếp cận phổ biến khác để lưu trữ thông tin ngày và giờ. Điều này là sử dụng trường INT để lưu trữ thời gian Unix (số giây đã trôi qua kể từ khi thành lập Giờ phối hợp quốc tế (UTC) vào ngày 1 tháng 1 năm 1970)

MySQL cũng cung cấp một cách để lưu một phần biểu diễn thời gian bằng cách sử dụng các kiểu Ngày, Năm hoặc thậm chí Thời gian. Vì bài viết này là về cách tốt nhất để lưu trữ một thời điểm chính xác, chúng tôi không bao gồm các loại bộ phận kém chính xác này trong cuộc thảo luận của chúng tôi

Sử dụng Loại INT với Unix Time

Sử dụng loại cột INT đơn giản để lưu trữ thời gian Unix là cách tiếp cận tầm thường nhất. Với INT, bạn có thể chắc chắn rằng số bạn đang lưu trữ có thể được chèn vào bảng một cách nhanh chóng và đáng tin cậy, như thế này

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);

Thats tất cả để có nó. Nó chỉ là một cột INT đơn giản và MySQL sẽ xử lý nó như vậy, sử dụng 4 byte để lưu trữ dữ liệu đó bên trong. Vì vậy, nếu bạn thực hiện CHỌN trên phần này, bạn sẽ nhận được một số, dấu chấm. Nếu bạn muốn thực hiện bất kỳ so sánh nào bằng cách sử dụng cột này làm ngày, thì truy vấn sau đây sẽ không hoạt động bình thường

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;

Điều này là do MySQL coi INT là một số, không phải là một ngày. Để thực hiện so sánh ngày, bạn phải lấy số giây đã trôi qua cho đến 2016-01-01 hoặc bạn sẽ cần sử dụng hàm FROM_UNIXTIME() MySQL để chuyển đổi cột INT thành Kiểu ngày. Truy vấn sau minh họa việc sử dụng hàm FROM_UNIXTIME()

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    FROM_UNIXTIME(measured_on) > '2016-01-01'
LIMIT 5;

Điều này sẽ truy xuất chính xác các bản ghi ngày sau 2016-01-01. Bạn cũng có thể so sánh trực tiếp số của mình với đại diện Unix của 2016-01-01, là 1451606400. Làm điều này có nghĩa là không cần sử dụng bất kỳ chức năng đặc biệt nào, vì bạn đang so sánh các số thẳng. Đây là truy vấn

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
   measured_on > 1451606400
LIMIT 5;

Điều gì sẽ xảy ra nếu việc thực hiện chuyển đổi này trước đơn giản là không hiệu quả hoặc thậm chí không khả thi? . Để thực hiện việc này mà không cần bất kỳ chức năng ngày nào của MySQL, bạn phải lấy dấu thời gian Unix cho ngày và giờ bắt đầu và kết thúc cho mỗi Thứ Tư trong năm 2016. Sau đó, bạn phải viết một truy vấn lớn sẽ có ít nhất 104 phép so sánh trong WHERE. (Có 52 ngày thứ Tư trong năm 2016 và bạn phải tính đến ngày bắt đầu (0. 00 am) và cuối ngày (11. 59. 59 giờ chiều). )

Điểm mấu chốt là cuối cùng thì rất có thể bạn sẽ sử dụng hàm chuyển đổi FROM_UNIXTIME(). Vì vậy, tại sao không thử các loại ngày thực tế?

Sử dụng Ngày giờ và Dấu thời gian

Ngày giờ và Dấu thời gian hoạt động khá giống nhau. Cả thông tin ngày và giờ lưu trữ với độ chính xác lên đến sáu chữ số trên giây phân số. Ngoài ra, sử dụng ngày mà con người có thể đọc được như '2016-01-01' (để tạo điều kiện so sánh) sẽ hiệu quả. Và cả hai định dạng đều hỗ trợ “định dạng thoải mái” khi thực hiện các truy vấn. Cú pháp thoải mái sẽ cho phép bất kỳ ký tự dấu chấm câu nào làm dấu phân cách. Chẳng hạn, lấy một chuỗi trong YYYY-MM-DD HH. MM. SS hoặc YY-MM-DD HH. MM. định dạng SS. Bất kỳ phiên bản nào trong số này sẽ hoạt động trong tình huống định dạng thoải mái

  • 2012-12-31 11. 30. 45
  • 2012^12^31 11+30+45
  • 31/12/2012 11*30*45
  • 2012@12@31 11^30^45

Các định dạng thoải mái khác được cho phép;

Theo mặc định, cả định dạng Ngày giờ và Dấu thời gian đều được truy xuất ở định dạng đầu ra tiêu chuẩn – năm-tháng-ngày giờ. phút. thứ hai (e. g. 2016-01-01 23. 59. 59). Nếu giây phân số được sử dụng, chúng sẽ xuất hiện sau giây dưới dạng giá trị thập phân (e. g. 2016-01-01 23. 59. 59. 5)

Sự khác biệt cốt lõi giữa Dấu thời gian và Ngày giờ liên quan chủ yếu đến cách MySQL thể hiện thông tin này trong nội bộ. cả hai đều được lưu trữ dưới dạng nhị phân chứ không phải chuỗi, nhưng Dấu thời gian sẽ sử dụng ít hơn một byte (bốn byte) so với Ngày giờ (năm byte) để biểu thị phần ngày/giờ. Cả hai sẽ sử dụng không gian bổ sung (1-3 byte) khi tiết kiệm giây phân số. Nếu bạn lưu trữ 1. 5 triệu bản ghi, sự khác biệt 1 byte này là không đáng kể

1. 5 triệu bản ghi * 1 byte bổ sung cho mỗi bản ghi / (1048576 byte/MB) = 1. 43 MB

Tiết kiệm một byte của dấu thời gian có giá. bạn chỉ có thể lưu trữ một giá trị từ '1970-01-01 00. 00. 01. 000000' đến '2038-01-19 03. 14. 07. 999999'. Tuy nhiên, Datetime cho phép bạn lưu bất kỳ giá trị nào từ '1000-01-01 00. 00. 00. 000000' đến '9999-12-31 23. 59. 59. 999999

Một sự khác biệt quan trọng - một điều mà nhiều nhà phát triển MySQL không biết - đó là MySQL sử dụng múi giờ của máy chủ để chuyển đổi giá trị Dấu thời gian thành giá trị UTC tương đương và lưu giá trị đó. Nó sẽ áp dụng lại chuyển đổi múi giờ khi truy xuất giá trị, vì vậy bạn sẽ nhận lại được giá trị ngày/giờ “gốc” của mình. Có lẽ. Đây là những gì có thể xảy ra

Lý tưởng nhất là nếu bạn ở cùng múi giờ, MySQL sẽ truy xuất cùng giá trị mà bạn đã lưu trữ. Theo kinh nghiệm của tôi, bạn có thể gặp sự cố nếu cơ sở dữ liệu của bạn xử lý thay đổi múi giờ. Chẳng hạn, điều này có thể xảy ra khi có sự thay đổi trong máy chủ (e. g. bạn thay đổi db của mình từ máy chủ ở Dublin thành máy chủ ở California hoặc bạn chỉ cần thay đổi múi giờ trong máy chủ). Dù bằng cách nào, nếu múi giờ của bạn khác khi bạn truy xuất dữ liệu, dữ liệu có thể bị ảnh hưởng

Các cột ngày giờ không bị thay đổi bởi db. Chúng sẽ lưu trữ và truy xuất cùng một giá trị mỗi lần, không phụ thuộc vào múi giờ đã định cấu hình. Cá nhân, tôi coi đây là một lựa chọn phù hợp hơn

Từ tài liệu MySQL

MySQL chuyển đổi các giá trị TIMESTAMP từ múi giờ hiện tại sang UTC để lưu trữ và ngược lại từ UTC sang múi giờ hiện tại để truy xuất. (Điều này không xảy ra đối với các loại khác, chẳng hạn như DATETIME, được lưu trữ "nguyên trạng". ) Theo mặc định, múi giờ hiện tại cho mỗi kết nối là thời gian của máy chủ. Múi giờ có thể được đặt trên cơ sở mỗi kết nối. Miễn là cài đặt múi giờ không đổi, bạn sẽ nhận lại cùng một giá trị mà bạn lưu trữ. Nếu bạn lưu trữ một giá trị DẤU THỜI GIAN, sau đó thay đổi múi giờ và truy xuất giá trị, thì giá trị được truy xuất sẽ khác với giá trị bạn đã lưu trữ. Điều này xảy ra do cùng một múi giờ không được sử dụng để chuyển đổi theo cả hai hướng. Múi giờ hiện tại có sẵn dưới dạng giá trị của biến hệ thống. Để biết thêm thông tin, “Hỗ trợ múi giờ của máy chủ MySQL”

Tóm tắt so sánh

Trước khi tìm hiểu sự khác biệt về hiệu suất thực tế khi sử dụng từng kiểu dữ liệu này, hãy xem xét một bảng tóm tắt sẽ cung cấp cho bạn một số hiểu biết sâu sắc hơn. Điểm yếu của từng loại có màu đỏ


FeatureDatetimeTimestampInt (lưu trữ thời gian Unix) Biểu diễn thời gian gốc Có Có Không, vì vậy hầu hết các hoạt động cần có chức năng chuyển đổi trước, như FROM_UNIXTIME() Có thể lưu trữ giây phân số Có, độ chính xác lên tới 6 chữ số Có, độ chính xác lên tới 6 chữ số Không Phạm vi hợp lệ'1000-01- . 00. 00. 000000'
đến
'9999-12-31 23. 59. 59. 999999'1970-01-01 00. 00. 01. 000000'
đến
'2038-01-19 03. 14. 07. 999999'Nếu chưa ký,
'1970-01-01 00. 00. 01. 000000;
về mặt lý thuyết lên tới
'2106-2-07 06. 28. 15'Tự động khởi tạo (MySQL 5. 6. 5+)CóCóKhôngGiải thích thoải mái (tài liệu MySQL)CóCóKhông, bạn phải sử dụng định dạng phù hợpGiá trị được thay đổi thành UTC khi được lưu trữKhôngCóKhôngCó thể được thay đổi thành loại khácCó, nếu giá trị dẫn đến phạm vi Dấu thời gian hợp lệCó, luôn luônCó, nếu giá trị dẫn đến phạm vi hợp lệ và . 6. 4+) 5 byte (cộng tối đa 3 byte cho giây phân số, nếu được sử dụng)4 byte (cộng tối đa 3 byte cho giây phân số, nếu được sử dụng . 7. Ngoài ra, hãy lưu ý những cân nhắc này khi cắt tỉa phân vùng. Có, sử dụng bất kỳ thao tác hợp lệ nào trên INT No, you have to format the outputPartitioningYesYes, using the ; any other expressions involving TIMESTAMP values are not permitted as per MySQL 5.7. Also, note these considerations on partition pruning.Yes, using any valid operation on INTs

Tốt nhất là nếu bạn ở cùng múi giờ, MySQL sẽ truy xuất cùng giá trị mà bạn đã lưu trữ. Theo kinh nghiệm của tôi, bạn có thể gặp sự cố nếu cơ sở dữ liệu của bạn xử lý thay đổi múi giờ. Chẳng hạn, điều này có thể xảy ra khi có sự thay đổi trong máy chủ (e. g. bạn thay đổi db của mình từ máy chủ ở Dublin thành máy chủ ở California hoặc bạn chỉ cần thay đổi múi giờ trong máy chủ). Dù bằng cách nào, nếu múi giờ của bạn khác khi bạn truy xuất dữ liệu, dữ liệu có thể bị ảnh hưởng.

Các cột ngày giờ không bị thay đổi bởi db. Chúng sẽ lưu trữ và truy xuất cùng một giá trị mỗi lần, không phụ thuộc vào múi giờ đã định cấu hình. Cá nhân, tôi coi đây là một lựa chọn phù hợp hơn

Từ tài liệu MySQL

MySQL chuyển đổi các giá trị TIMESTAMP từ múi giờ hiện tại sang UTC để lưu trữ và ngược lại từ UTC sang múi giờ hiện tại để truy xuất. (Điều này không xảy ra đối với các loại khác, chẳng hạn như DATETIME, được lưu trữ "nguyên trạng". ) Theo mặc định, múi giờ hiện tại cho mỗi kết nối là thời gian của máy chủ. Múi giờ có thể được đặt trên cơ sở mỗi kết nối. Miễn là cài đặt múi giờ không đổi, bạn sẽ nhận lại cùng một giá trị mà bạn lưu trữ. Nếu bạn lưu trữ một giá trị DẤU THỜI GIAN, sau đó thay đổi múi giờ và truy xuất giá trị, thì giá trị được truy xuất sẽ khác với giá trị bạn đã lưu trữ. Điều này xảy ra do cùng một múi giờ không được sử dụng để chuyển đổi theo cả hai hướng. Múi giờ hiện tại có sẵn dưới dạng giá trị của biến hệ thống. Để biết thêm thông tin, “Hỗ trợ múi giờ của máy chủ MySQL”

Tóm tắt so sánh

Trước khi tìm hiểu sự khác biệt về hiệu suất thực tế khi sử dụng từng kiểu dữ liệu này, hãy xem xét một bảng tóm tắt sẽ cung cấp cho bạn một số hiểu biết sâu sắc hơn. Điểm yếu của từng loại có màu đỏ

Điểm chuẩn Hiệu suất INT, Dấu thời gian và Ngày giờ

Để so sánh hiệu suất của từng loại này, tôi đang sử dụng 1. 5 triệu bản ghi (chính xác hơn là 1.497.421) từ mạng lưới trạm thời tiết do tôi xây dựng. Mạng này thu thập dữ liệu mỗi phút. Để làm cho các thử nghiệm này có thể nhân rộng, tôi đã xóa một số cột riêng tư để bạn có thể chạy thử nghiệm của riêng mình trên dữ liệu này

Từ bảng ban đầu của tôi, tôi đã tạo ba phiên bản

  • Bảng
    SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
    LIMIT 5;
    
    7 sử dụng Ngày giờ trong cột
    SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
    LIMIT 5;
    
    8 để biểu thị thời điểm ghi lại bản ghi trạm thời tiết
  • Bảng
    SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
    LIMIT 5;
    
    9 sử dụng Dấu thời gian cho cột
    SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
    LIMIT 5;
    
    8
  • SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        FROM_UNIXTIME(measured_on) > '2016-01-01'
    LIMIT 5;
    
    1 sử dụng INT (không dấu) cho cột
    SELECT 
        id, measured_on, FROM_UNIXTIME(measured_on)
    FROM
        vertabelo.inttimestampmeasures
    WHERE
        measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
    LIMIT 5;
    
    8

Ba bảng này có cùng một dữ liệu; . Tất cả các bảng đều có chỉ mục được đặt trên cột

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
8




Công cụ điểm chuẩn

Để đánh giá hiệu suất của các kiểu dữ liệu này, tôi đã sử dụng hai phương pháp. Một dựa trên Sysbench, mà trang web của nó mô tả là

“. một công cụ điểm chuẩn mô-đun, đa nền tảng và đa luồng để đánh giá các thông số hệ điều hành quan trọng đối với hệ thống chạy cơ sở dữ liệu dưới tải nặng. ”

Công cụ này được đề xuất trong tài liệu MySQL

Nếu bạn đang sử dụng Windows (như tôi), bạn có thể tải xuống tệp zip chứa các tệp thực thi và truy vấn kiểm tra mà tôi đã sử dụng. Chúng được dựa trên một phương pháp được đề xuất để đo điểm chuẩn

Để chạy thử nghiệm nhất định, bạn có thể sử dụng lệnh sau (chèn tham số kết nối của riêng bạn)

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
4

Điều này hoạt động khi

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    FROM_UNIXTIME(measured_on) > '2016-01-01'
LIMIT 5;
5 là tệp thử nghiệm và có truy vấn SQL từ mỗi thử nghiệm trỏ đến từng bảng

Để xác thực thêm kết quả, tôi cũng đang chạy mysqlslap. Một lần nữa, từ trang web của họ

“mysqlslap là một chương trình chẩn đoán được thiết kế để mô phỏng tải máy khách cho máy chủ MySQL và báo cáo thời gian của từng giai đoạn. Nó hoạt động như thể nhiều khách hàng đang truy cập vào máy chủ. ”

Nhớ lại rằng điều quan trọng từ những bài kiểm tra này không phải là thời gian tuyệt đối cần thiết. Đó là thời gian kết quả tương đối khi chạy cùng một truy vấn trên các kiểu dữ liệu khác nhau. Thời gian thử nghiệm của hai công cụ benchmark không nhất thiết phải giống nhau vì mỗi công cụ hoạt động khác nhau. Điều quan trọng là so sánh kiểu dữ liệu, điều này sẽ rõ ràng khi chúng ta đi sâu hơn vào các bài kiểm tra

Các bài kiểm tra điểm chuẩn

Tôi sẽ sử dụng ba truy vấn cho phép chúng tôi đánh giá một số khía cạnh hiệu suất

  • Lựa chọn phạm vi thời gian
    • Điều này cho phép chúng tôi thực hiện so sánh trực tiếp mà không cần sử dụng bất kỳ hàm ngày đặc biệt nào trên kiểu dữ liệu Ngày giờ và Dấu thời gian
    • Đồng thời, chúng ta có thể đánh giá tác động của việc sử dụng hàm ngày trong cột loại INT so với việc sử dụng phép so sánh số đơn giản trên trường này. Chúng tôi sẽ cần chuyển đổi phạm vi thành số Unix cho việc này
  • Lựa chọn chức năng ngày
    • Điều này cho phép đánh giá hiệu suất của việc sử dụng hàm ngày tháng như một phần của mệnh đề “WHERE”, trái ngược với thử nghiệm trước đây khi so sánh được thực hiện với giá trị NGÀY đơn giản
    • Chúng tôi cũng có thể kiểm tra một tình huống trong đó chúng tôi được yêu cầu sử dụng một hàm để chuyển đổi cột INT thành loại DATE hợp lệ và sau đó thực hiện truy vấn
  • Truy vấn đếm ()
    • Là một phụ lục cho truy vấn trước đó, điều này sẽ đánh giá cách một truy vấn tóm tắt điển hình thực hiện với ba loại biểu diễn khác nhau của chúng tôi

Chúng tôi sẽ đề cập đến một số tình huống phổ biến với các thử nghiệm này và chúng tôi sẽ xem hiệu suất hoạt động như thế nào với cả ba loại

Giới thiệu về SQL_NO_CACHE

Khi sử dụng SQL_NO_CACHE trong truy vấn, máy chủ không sử dụng bộ đệm truy vấn. Nó không kiểm tra bộ đệm truy vấn để xem kết quả đã có chưa và cũng không lưu trữ kết quả truy vấn. Do đó, mỗi truy vấn sẽ phản ánh tác động hiệu suất thực tế như khi nó được gọi lần đầu tiên

kiểm tra 1. Chọn giá trị trong phạm vi ngày

Truy vấn này trả về 75.706 hàng từ 1.497.421 số đo có sẵn

Truy vấn 1 với DATETIME
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
6
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin152296Max12613203Average362809

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
7
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
8
Truy vấn 1 với Dấu thời gian
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
0
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin214359Max13893313Average4311004

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
1
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
2
Truy vấn 1 với INT
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
3
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin24727968Max655410312Average41078527

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
4
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
5
Truy vấn thay thế 1 với INT

Vì đây là một tìm kiếm theo phạm vi khá đơn giản và ngày tháng trong truy vấn có thể dễ dàng dịch sang phép so sánh số đơn giản, nên tôi đã đưa nó vào thử nghiệm này. Nó hóa ra là nhanh nhất (như bạn có thể dự đoán), vì nó chỉ so sánh các con số và không sử dụng bất kỳ chức năng chuyển đổi ngày nào

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
6
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin88171Max2752157Average165514

CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
7
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
8
KIỂM TRA 1 TỔNG KẾT
Thời gian phản hồi trung bình (mili giây)SysbenchSpeed ​​So với DatetimemysqlslapSpeed ​​So với DatetimeDatetime362-809-Timestamp43119% chậm hơn100424% chậm hơnINT41071134% chậm hơn85271054% chậm hơnTruy vấn INT thay thế16555% nhanh hơn51436% nhanh hơn

Cả hai công cụ điểm chuẩn đều cho thấy rằng . Nhưng Datetime không nhanh hơn so với việc sử dụng phép so sánh số đơn giản, như chúng ta đã sử dụng trong truy vấn INT thay thế.

kiểm tra 2. Chọn các giá trị được tạo vào các ngày thứ Hai

Truy vấn này trả về 221.850 hàng từ 1.497.421 số đo có sẵn

Truy vấn 2 với Datetime
CREATE TABLE `timestamp_example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `measured_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `measured_on` (`measured_on`)
) ENGINE=InnoDB;
9
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin18744343Max61687797Average31276103

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
0
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
1
Truy vấn 2 với Dấu thời gian
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
2
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin26885953Max666613531Average36538412

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
3
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
4
Truy vấn 2 với INT
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
5
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin20515844Max700710469Average34868088

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
6
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
7
TỔNG KẾT KIỂM TRA 2
Thời gian phản hồi trung bình (mili giây)Tốc độ của Sysbench so với DatetimemysqlslapTốc độ so với DatetimeDatetime3127-6103-Timestamp365317% chậm hơn841238% chậm hơnINT348611% chậm hơn808832% chậm hơn

Một lần nữa, trong cả hai công cụ điểm chuẩn, Ngày giờ nhanh hơn so với Dấu thời gian . Nhưng trong thử nghiệm này, truy vấn INT – mặc dù nó sử dụng hàm để chuyển đổi ngày – cho kết quả nhanh hơn truy vấn Dấu thời gian.

kiểm tra 3. Chọn Số Biện pháp được Tạo vào Thứ Hai

Truy vấn này trả về một hàng với số lượng biện pháp xảy ra vào Thứ Hai (từ 1.497.421 biện pháp có sẵn)

Truy vấn 3 với Datetime
INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
8
Hiệu suất
Thời gian phản hồi (ms)SysbenchmysqlslapMin17204063Max45947812Average27975540

INSERT INTO `vertabelo`.`sampletable`
(
 `id`,
 `measured_on` #INT TYPE COLUMN
)
VALUES
(
 1,
 946684801 
 #unix stamp equivalent to 01/01/2000 @ 12:00am (UTC) http://unixtimestamp.com
);
9
SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
0
Truy vấn 3 với Dấu thời gian
SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
1
Hiệu suất
Thời gian phản hồi (mili giây)SysbenchmysqlslapMin19074578Max543710235Trung bình34087102

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
2
SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
3
Truy vấn 3 với INT
SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
4
Hiệu suất
Thời gian phản hồi (mili giây)SysbenchmysqlslapMin21085609Max47649735Trung bình33077416

SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
5
SELECT 
    id, measured_on, FROM_UNIXTIME(measured_on)
FROM
    vertabelo.inttimestampmeasures
WHERE
    measured_on > '2016-01-01' #measured_on is compared as a string to resolve the query
LIMIT 5;
6
TỔNG KẾT BÀI KIỂM TRA 3
Thời gian phản hồi trung bình (mili giây)Tốc độ của Sysbench so với DatetimemysqlslapSpeed ​​So với DatetimeDatetime2797-5540-Timestamp340822% chậm hơn710228% chậm hơnINT330718% chậm hơn741633% chậm hơn

Một lần nữa, cả hai công cụ điểm chuẩn đều cho thấy Datetime nhanh hơn . Không thể kết luận nếu INT nhanh hơn Dấu thời gian, vì mysqlslap cho thấy phản hồi nhanh hơn một chút cho Dấu thời gian và Sysbench cho thấy điều ngược lại.

Ghi chú. Tất cả các thử nghiệm đều được chạy cục bộ trong máy Windows 10 với CPU i7 lõi ​​kép và RAM 16 GB, chạy MariaDb v10. 1. 9 công cụ sử dụng innoDb

Phần kết luận

Dựa trên dữ liệu này, tôi tin rằng Datetime là lựa chọn tốt nhất trong hầu hết các tình huống. Đây là lý do tại sao

  • Nó nhanh hơn (theo ba điểm chuẩn của chúng tôi)
  • Con người có thể đọc được mà không cần chuyển đổi
  • Không có vấn đề do chuyển đổi múi giờ
  • Nó chỉ sử dụng nhiều hơn 1 byte so với các đối tác của nó
  • Nó cho phép phạm vi ngày lớn hơn (từ năm 1000 đến 9999)

Nếu bạn chỉ đang lưu trữ dấu thời gian Unix (và bạn đang ở trong phạm vi ngày hợp lệ của dấu thời gian đó) và bạn thực sự không định sử dụng bất kỳ truy vấn dựa trên ngày nào trên dấu thời gian đó, tôi khuyên bạn nên sử dụng INT. Chúng tôi đã thấy rằng nó thực hiện các truy vấn so sánh số đơn giản rất nhanh khi bạn đang làm việc với một số đơn giản

Còn Dấu thời gian thì sao? . Sau khi đọc bài viết này, bạn sẽ hiểu rõ hơn về sự khác biệt giữa cả ba loại và có thể đưa ra lựa chọn tốt nhất cho nhu cầu của mình

Ngày được viết trong MySQL như thế nào?

MySQL truy xuất và hiển thị các giá trị NGÀY ở định dạng ' YYYY-MM-DD '. Phạm vi được hỗ trợ là '1000-01-01' đến '9999-12-31'. Loại DATETIME được sử dụng cho các giá trị chứa cả phần ngày và giờ. MySQL truy xuất và hiển thị các giá trị DATETIME trong ' YYYY-MM-DD hh. mm. định dạng ss.

Định dạng để chèn ngày trong MySQL là gì?

Ngày là số nguyên hay varchar?

Ngày dương lịch được lưu trữ nội bộ dưới dạng số nguyên giá trị bằng với số ngày kể từ ngày 31 tháng 12 năm 1899. Vì các giá trị NGÀY được lưu dưới dạng số nguyên nên bạn có thể sử dụng chúng trong các biểu thức số học.

Làm cách nào để lấy ngày ở định dạng dd mm yyyy trong MySQL?

Sau đây là truy vấn để định dạng ngày thành YYYY-MM-DD. mysql> select str_to_date(LoginDate,'%d. %m .