国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??

這篇具有很好參考價值的文章主要介紹了MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??

前言

在MySQL中時間類型的選擇有很多,比如:date、time、year、datetime、timestamp...

在某些情況下還會使用整形int、bigint來存儲時間戳

根據(jù)節(jié)省空間的原則,當只需要存儲年份、日期、時間時,可以使用year、date、time

如果需要詳細的時間,可以選擇datetime、timestamp或者使用整形來存儲時間戳

以下是不同類型的格式、時間范圍、占用空間相關信息

類型 格式 范圍 空間(字節(jié)Byte)
date YYYY-MM-DD 1000-01-01 to9999-12-31 3
time hh:mm:ss.fraction -838:59:59.000000 to 838:59:59.000000 3
year YYYY 1901 to 2155 1
datetime YYYY-MM-DD hh:mm:ss[.fraction] 1000-01-01 00:00:00.000000 to 9999-12-31 23:59:59.499999 8
timestamp 存儲為時間戳,顯示為YYYY-MM-DD hh:mm:ss 1970-01-01 00:00:01.000000 UTC to 2038-01-19 03:14:07.499999 UTC 4
int 時間戳 4
bigint 時間戳 8

本篇文章主要概述datetime、timestamp與整形時間戳相關的內容,并在千萬級別的數(shù)據(jù)量中測試它們的性能,最后總結出它們的特點與使用場景

datetime

datetime不僅可以存儲日期、時間,還可以存儲小數(shù)點后續(xù)的毫秒等 YYYY-MM-DD hh:mm:ss[.fraction]

比如datetime(3) 就可以保留三位小數(shù) 2023-04-22 20:47:32.000

當datetime不保留小數(shù)時使用5 Byte,需要保留小數(shù)時多加3 Byte,總共8 Byte (5.6.X之后)

datetime是最常用的時間類型,在存儲、讀取的性能和數(shù)據(jù)庫可視化方面都不錯,但它只能展示固定的時間,如果在不同時區(qū),看到的時間依舊是固定的,不會隨著時間變化

timestamp 時間戳

MySQL中的timestamp能有效的解決時區(qū)問題

timestamp用于存儲時間戳,在進行存儲時會先將時間戳轉換為UTC

UTC是世界統(tǒng)一時間,比如我們的時區(qū)為東八區(qū),則是在UTC的基礎上增加八小時

時間戳在進行存儲時,先根據(jù)當前時區(qū)轉換成UTC,再轉換成int類型進行存儲

時間戳在進行讀取時,先將int類型轉換為UTC,再轉換為當前時區(qū)

MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??

當前時區(qū)指的是MySQL服務端本地時區(qū),默認為系統(tǒng)時區(qū),可以進行配置

當前時區(qū)發(fā)生變化時,讀取時間戳會發(fā)生變化

比如我的服務端默認系統(tǒng)為東八區(qū)(+8:00),當我修改為(+11:00)

[mysqld]
default_time_zone = +11:00

讀取時,所有的timestamp都增加3小時

MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??

如果MySQL時區(qū)設置為系統(tǒng)時區(qū)(time_zone = SYSTEM)時,進行時區(qū)轉換會調用系統(tǒng)函數(shù),高并發(fā)下開銷會很大

MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??

	@Resource
    private JdbcTemplate jdbcTemplate;

    @Test
    /**
     * 10個線程每次查詢10次  一次查500條
     * timestamp:11,978ms
     * datetime:9,057ms
     */
    void getTimestamp() throws BrokenBarrierException, InterruptedException {
        String timestampSql = "select SQL_NO_CACHE test_timestamp from datetime_test  where test_timestamp >= '2022-10-10 00:00:00' and test_timestamp <= '2022-10-11 00:00:00' order by test_timestamp  limit 500;";
        String dateTimeSql = "select SQL_NO_CACHE test_datetime from datetime_test  where test_datetime >= '2022-10-10 00:00:00' and test_datetime <= '2022-10-11 00:00:00' order by test_datetime  limit 500;";

        CountDownLatch countDownLatch = new CountDownLatch(10);
        long start = System.currentTimeMillis();
        forQuery(timestampSql, countDownLatch);

        countDownLatch.await();
        //timestamp:11,978ms
        System.out.println(MessageFormat.format("timestamp:{0}ms", System.currentTimeMillis() - start));

        CountDownLatch countDownLatch2 = new CountDownLatch(10);
        start = System.currentTimeMillis();
        forQuery(dateTimeSql, countDownLatch2);
        countDownLatch2.await();
        //datetime:9,057ms
        System.out.println(MessageFormat.format("datetime:{0}ms", System.currentTimeMillis() - start));
    }

    private void forQuery(String timestampSql, CountDownLatch countDownLatch) {
        for (int j = 1; j <= 10; j++) {
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    jdbcTemplate.queryForList(timestampSql);
                }
                countDownLatch.countDown();
            }).start();
        }
    }

timestamp 時間戳使用整形進行存儲,占用4Byte空間

timestamp范圍有限'1970-01-01 00:00:01.000000'UTC 到'2038-01-19 03:14:07.499999'UTC ,2038年XX后的時間需要其他解決方案進行處理

timestamp當時區(qū)發(fā)生改變時讀取數(shù)據(jù)會有變化,由于存儲、讀取都需要根據(jù)時區(qū)對數(shù)據(jù)進行轉換,因此性能也會有一定的開銷,同時由于時間有限,還需要提供超出時間后的解決方案

整形時間戳

上文說到timestamp存儲時間戳使用整形來存儲,只是存儲、讀取會將時間戳轉換為當前時區(qū)的時間

其實我們還可以通過整形自己進行存儲,比如使用int直接存儲時間戳

但由于int整形只有4B(時間范圍有限),在未來可能無法進行存儲時間,就需要其他方案解決

為了避免空間太小,可以直接使用bigint 8B進行存儲

使用整形存儲時間戳不需要轉換成時區(qū),因此沒有轉換的性能開銷,但無法顯示時間、可讀性不好,可以由我們自由進行時區(qū)轉換適合國際化

千萬數(shù)據(jù)測試

為了比較datetime、timestamp、bigint的性能,我們需要先搭建環(huán)境

案例只測試innodb存儲引擎有索引的情況,想測試其他情況的同學,可以使用以下腳本函數(shù)自由測試

首先拿出一個快過期的云服務器,然后在服務器上啟動MySQL,待會用函數(shù)狠狠的把它的CPU跑滿

搭建環(huán)境

查看是否開啟函數(shù)創(chuàng)建

#開啟函數(shù)創(chuàng)建
set global log_bin_trust_function_creators=1;

#ON表示已開啟
show variables like 'log_bin_trust%';

創(chuàng)建表,表中數(shù)據(jù)類型為bigint、datetime、timestamp進行測試

(先不要創(chuàng)建索引,因為生成的時間是隨機無序的,維護索引的開銷會很大,等數(shù)據(jù)跑完后續(xù)再生成索引)

CREATE TABLE `datetime_test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  `test_datetime` datetime DEFAULT NULL,
  `test_timestamp` timestamp NULL DEFAULT NULL,
  `test_bigint` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

隨機生成字符串的函數(shù)

#分割符從;改為$$
delimiter $$
#函數(shù)名ran_string 需要一個參數(shù)int類型 返回類型varchar(255)
create function ran_string(n int) returns varchar(255)
begin
#聲明變量chars_str默認'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
#聲明變量return_str默認''
declare return_str varchar(255) default '';
#聲明變量i默認0
declare i int default 0;
#循環(huán)條件 i<n
while i < n do
set return_str = concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i=i+1;
end while;
return return_str;
end $$

隨機生成整形的函數(shù)

#生成隨機num的函數(shù)
delimiter $$
create function rand_num() returns int(5)
begin
declare i int default 0;
set i=floor(100+rand()*10);
return i;
end $$

編寫插入函數(shù)

其中使用UNIX_TIMESTAMP函數(shù)將時間轉化為時間戳存入bigint中

#插入 從參數(shù)start開始 插入max_num條數(shù)據(jù)(未使用startc)
delimiter $$ 
create procedure insert_datetime_test(in start int(10),in max_num int(10))
begin
declare i int default 0;
declare random datetime default '2022-01-01 00:00:00';
set autocommit = 0;
repeat
set i = i+1;
set random = DATE_ADD('2022-01-01 00:00:00', INTERVAL FLOOR(RAND() * 31536000) SECOND);
#SQL 語句
insert into datetime_test(username,money,test_bigint,test_datetime,test_timestamp) 
values (ran_string(8),rand_num(),UNIX_TIMESTAMP(random),random,random);
until i=max_num
end repeat;
commit;
end $$

執(zhí)行

#執(zhí)行插入函數(shù)
delimiter ;
call insert_datetime_test(1,10000000);

我生成的是兩千萬條數(shù)據(jù),想生成別的數(shù)量也可以設置call insert_datetime_test(1,10000000)

建索引
alter table datetime_test add index idx_datetime(test_datetime);
alter table datetime_test add index idx_timestamp(test_timestamp);
alter table datetime_test add index idx_bigint(test_bigint);

根據(jù)時間段查詢數(shù)據(jù)(需要回表)

與時間相關、最常見的功能就是根據(jù)時間段進行查詢數(shù)據(jù),比如想查詢2022-10-10這一天的下單數(shù)據(jù)

為了模擬真實場景,這里將查詢列表設置為*,讓MySQL回表查詢其他數(shù)據(jù)

(回表:使用二級索引后,需要回表查詢聚簇【主鍵】索引獲取全部數(shù)據(jù),可能導致隨機IO)

根據(jù)時間段查詢少量數(shù)據(jù)

select SQL_NO_CACHE * from datetime_test 
where test_datetime >= '2022-10-10 00:00:00' and test_datetime <= '2022-10-11 00:00:00'
order by test_datetime 
limit 20
> OK
> 時間: 0.038s


select SQL_NO_CACHE * from datetime_test 
where test_timestamp >= '2022-10-10 00:00:00' and test_timestamp <= '2022-10-11 00:00:00'
order by test_timestamp 
limit 20
> OK
> 時間: 0.034s


select SQL_NO_CACHE * from datetime_test 
where test_bigint >= 1665331200 and test_bigint <= 1665417600
order by test_bigint 
limit 20
> OK
> 時間: 0.036s

由于數(shù)據(jù)量比較小,回表次數(shù)少、隨機IO少,會更傾向于使用索引

三種類型查詢時間差不多

根據(jù)時間段查詢大量數(shù)據(jù) (數(shù)據(jù)量5.5W)

一般也不會根據(jù)時間段一次性查這么多數(shù)據(jù),主要是想看下性能

select SQL_NO_CACHE * from datetime_test 
where test_datetime >= '2022-10-10 00:00:00' and test_datetime <= '2022-10-11 00:00:00'
> OK
> 時間: 37.084s


select SQL_NO_CACHE * from datetime_test 
where test_timestamp >= '2022-10-10 00:00:00' and test_timestamp <= '2022-10-11 00:00:00'
> OK
> 時間: 39.558s


select SQL_NO_CACHE * from datetime_test 
where test_bigint >= 1665331200 and test_bigint <= 1665417600
> OK
> 時間: 38.966s

主要的性能開銷是需要回表查數(shù)據(jù),三種類型性能都差不多 datetime > bigint > timestamp

由于回表的開銷可能會影響我們的結果,因此還是要看不回表的案例

根據(jù)時間段查詢數(shù)據(jù)(不回表)

select SQL_NO_CACHE test_datetime from datetime_test 
where test_datetime >= '2022-10-10 00:00:00' and test_datetime <= '2022-10-11 00:00:00'
> OK
> 時間: 8.478s


select SQL_NO_CACHE test_timestamp from datetime_test 
where test_timestamp >= '2022-10-10 00:00:00' and test_timestamp <= '2022-10-11 00:00:00'
> OK
> 時間: 9.063s


select SQL_NO_CACHE test_bigint from datetime_test 
where test_bigint >= 1665331200 and test_bigint <= 1665417600
> OK
> 時間: 5.773s

測試不用回表時,三種類型的性能差異還是比較顯著的,bigint > datetime > timestamp

但根據(jù)時間段不回表的查詢場景還是比較少的,除非用聯(lián)合索引,時間加上另一個需要的值

統(tǒng)計數(shù)量

根據(jù)時間統(tǒng)計數(shù)量的場景還是比較多的:統(tǒng)計某天、某月下單數(shù)量等...

統(tǒng)計部分數(shù)據(jù)

select SQL_NO_CACHE count(*) from datetime_test 
where test_datetime >= '2022-10-10 00:00:00' and test_datetime <= '2022-10-11 00:00:00'
> OK
> 時間: 0.053s


select SQL_NO_CACHE count(*) from datetime_test 
where test_timestamp >= '2022-10-10 00:00:00' and test_timestamp <= '2022-10-11 00:00:00'
> OK
> 時間: 0.078s


select SQL_NO_CACHE count(*) from datetime_test 
where test_bigint >= 1665331200 and test_bigint <= 1665417600
> OK
> 時間: 0.049s

統(tǒng)計所有數(shù)據(jù)

select SQL_NO_CACHE count(*) from datetime_test
> OK
> 時間: 3.898s


select SQL_NO_CACHE count(*) from datetime_test
> OK
> 時間: 4.152s


select SQL_NO_CACHE count(*) from datetime_test
> OK
> 時間: 3.17s

統(tǒng)計數(shù)量count 可以直接使用二級索引,不需要回表

性能:bigint > datetime > timestamp

經過不回表的測試bigint是性能最好的,與datetime相比性能提升在10%~30%之間

總結

當只需要存儲年份、日期、時間時,可以使用year、date、time,盡量使用少的空間

datetime性能不錯,方便可視化,固定時間,可以在不追求性能、方便可視化、不涉及時區(qū)的場景使用

timestamp性能較差,存儲時間戳,涉及時區(qū)轉換(如果是系統(tǒng)時區(qū)高并發(fā)下性能更差),有時間范圍限制,還需要為未來準備解決方案(感覺比較雞肋)

bigint性能最好,存儲時間戳,不方便可視化,由自己自由轉換時區(qū),適合追求性能、國際化(時區(qū)轉換)、不注重DB可視化的場景,還不用考慮時間范圍,如果是短期不會超出2038年XX還可以使用空間更小的int整形

最后(不要白嫖,一鍵三連求求拉~)

本篇文章被收入專欄 由點到線,由線到面,構建MySQL知識體系,感興趣的同學可以持續(xù)關注喔

本篇文章筆記以及案例被收入 gitee-StudyJava、 github-StudyJava 感興趣的同學可以stat下持續(xù)關注喔~

案例地址:

Gitee-JavaConcurrentProgramming/src/main/java/G_ThreadLocal

Github-JavaConcurrentProgramming/src/main/java/G_ThreadLocal

有什么問題可以在評論區(qū)交流,如果覺得菜菜寫的不錯,可以點贊、關注、收藏支持一下~

關注菜菜,分享更多干貨,公眾號:菜菜的后端私房菜

本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!文章來源地址http://www.zghlxwxcb.cn/news/detail-711585.html

到了這里,關于MySQL字段的時間類型該如何選擇?千萬數(shù)據(jù)下性能提升10%~30%??的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • MySQL相關的SQL語句、數(shù)據(jù)庫、數(shù)據(jù)表、字段、類型

    1、 SQL 語句不區(qū)分大小寫。 SQL語句 用途 描述 mysql -u root -p 連接 MySQL 在命令行窗口中輸入 mysql -u root -p 命令,回車,然后輸入 MySQL 密碼(不要忘記了密碼,找回麻煩),再回車就連接上 MySQL 了。最初都是使用 root 用戶登錄,工作中不能一直使用 root 用戶登錄。因為 root 權限太

    2024年02月13日
    瀏覽(115)
  • mysql數(shù)據(jù)庫存儲手機號字段選擇bigint還是char?

    在MySQL中,存儲手機號可以使用多種數(shù)據(jù)類型,包括bigint、char、varchar等。不同的數(shù)據(jù)類型有不同的優(yōu)缺點,因此需要根據(jù)實際情況選擇合適的數(shù)據(jù)類型。 bigint類型 bigint類型是一種整數(shù)類型,可以存儲很大的整數(shù),范圍為-9223372036854775808到9223372036854775807。因此,如果使用big

    2024年02月11日
    瀏覽(31)
  • Java項目中,MySQL數(shù)據(jù)庫中的時間字段用哪個?

    1.timestamp: ? ? ? ? ? ? ? ? 自帶時區(qū)屬性,該類型的字段會隨著服務器時區(qū)的變化而變化,自動換算成相應時區(qū)的時間,存儲形式為:yyyy-MM-dd HH:mm:ss,對應的Java類型為java.sql.Timestamp ? ? ? ? ? ? ? ? 缺點:只能存儲到2038年的時間。 2.datetime: ? ? ? ? ? ? ? ? 不具備時區(qū)

    2024年02月10日
    瀏覽(16)
  • 【MySQL】MySQL 數(shù)據(jù)類型,數(shù)值、日期和時間、字符串類型,創(chuàng)建數(shù)據(jù)表,刪除數(shù)據(jù)表

    【MySQL】MySQL 數(shù)據(jù)類型,數(shù)值、日期和時間、字符串類型,創(chuàng)建數(shù)據(jù)表,刪除數(shù)據(jù)表

    作者簡介: 辭七七,目前大一,正在學習C/C++,Java,Python等 作者主頁: 七七的個人主頁 文章收錄專欄: 七七的閑談 歡迎大家點贊 ?? 收藏 ? 加關注哦!???? MySQL 中定義數(shù)據(jù)字段的類型對你數(shù)據(jù)庫的優(yōu)化是非常重要的。 MySQL 支持多種類型,大致可以分為三類:數(shù)值、日

    2024年02月15日
    瀏覽(111)
  • 【?MySQL | 數(shù)據(jù)類型(一)】簡介 | 整數(shù) | 浮點 | 定點 | 時間/日期類型

    【?MySQL | 數(shù)據(jù)類型(一)】簡介 | 整數(shù) | 浮點 | 定點 | 時間/日期類型

    ?歡迎來到小K的MySQL專欄,本節(jié)將為大家?guī)鞰ySQL數(shù)據(jù)類型簡介 | 整數(shù) | 浮點 | 定點 | 時間/日期類型的分享 ? 0.數(shù)據(jù)類型簡介 數(shù)據(jù)類型(data_type)是指系統(tǒng)中所允許的數(shù)據(jù)的類型。MySQL 數(shù)據(jù)類型定義了列中可以存儲什么數(shù)據(jù)以及該數(shù)據(jù)怎樣存儲的規(guī)則。 數(shù)據(jù)庫中的每個列都

    2024年02月11日
    瀏覽(20)
  • 【Flink-Kafka-To-Mongo】使用 Flink 實現(xiàn) Kafka 數(shù)據(jù)寫入 Mongo(根據(jù)對應操作類型進行增、刪、改操作,寫入時對時間類型字段進行單獨處理)

    需求描述: 1、數(shù)據(jù)從 Kafka 寫入 Mongo。 2、相關配置存放于 Mysql 中,通過 Mysql 進行動態(tài)讀取。 3、此案例中的 Kafka 是進行了 Kerberos 安全認證的,如果不需要自行修改。 4、Kafka 數(shù)據(jù)為 Json 格式,獲取到的數(shù)據(jù)根據(jù)操作類型字段進行增刪改操作。 5、讀取時使用自定義 Source,寫

    2024年02月22日
    瀏覽(30)
  • sql字段類型和時間格式轉換

    在SQL中,字段類型格式轉換是指將數(shù)據(jù)從一種數(shù)據(jù)類型轉換為另一種數(shù)據(jù)類型的過程。這通常涉及將字符串轉換為日期、將數(shù)字轉換為字符串、將整數(shù)轉換為浮點數(shù)等。 SQL字段類型格式轉換的原理如下: 顯式轉換:顯式轉換是指用戶明確指定要執(zhí)行的數(shù)據(jù)類型轉換。這可以

    2024年02月08日
    瀏覽(21)
  • 千萬級數(shù)據(jù)深分頁查詢SQL性能優(yōu)化實踐

    如何在Mysql中實現(xiàn)上億數(shù)據(jù)的遍歷查詢?先來介紹一下系統(tǒng)主角:關注系統(tǒng),主要是維護京東用戶和業(yè)務對象之前的關注關系;并對外提供各種關系查詢,比如查詢用戶的關注商品或店鋪列表,查詢用戶是否關注了某個商品或店鋪等。但是最近接到了一個新需求,要求提供查

    2024年02月11日
    瀏覽(30)
  • elasticsearch 將時間類型為時間戳保存格式的時間字段格式化返回
  • Java中處理千萬級數(shù)據(jù)的最佳實踐:性能優(yōu)化指南

    在今天的數(shù)字化時代,處理大規(guī)模數(shù)據(jù)已經成為許多Java應用程序的核心任務。無論您是構建數(shù)據(jù)分析工具、實現(xiàn)實時監(jiān)控系統(tǒng),還是處理大規(guī)模日志文件,性能優(yōu)化都是確保應用程序能夠高效運行的關鍵因素。本指南將介紹一系列最佳實踐,幫助您在處理千萬級數(shù)據(jù)時提高

    2024年02月03日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包