日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql datetime 后面带了很多0_面试官:MySQL 表设计要注意什么?

發(fā)布時間:2025/3/12 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql datetime 后面带了很多0_面试官:MySQL 表设计要注意什么? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
作者 孤獨煙來自公眾號:孤獨煙

引言

大家應(yīng)該知道煙哥最近要(tiao 咳咳咳),嗯,不可描述!

隨手講其中一部分知識,都是一些煙哥自己平時工作的總結(jié)以及經(jīng)驗。大家看完,其實能避開很多坑。而且很多問題,都是面試中實打?qū)崟柕降?#xff01;

比如

OK,具體有下面這些問題

  • 1、為什么一定要設(shè)一個主鍵?
  • 2、你們主鍵是用自增還是UUID?
  • 3、主鍵為什么不推薦有業(yè)務(wù)含義?
  • 4、表示枚舉的字段為什么不用enum類型?
  • 5、貨幣字段用什么類型?
  • 6、時間字段用什么類型?
  • 7、為什么不直接存儲圖片、音頻、視頻等大容量內(nèi)容?
  • 8、字段為什么要定義為NOT NULL?

其實上面這些問題,我最早想法是,每個問題都可以啰嗦出一篇文章。后來由于良心發(fā)現(xiàn),煙哥就決定用一篇文章將這些問題都講明白。

當(dāng)然,我給的回答可能并非標(biāo)準(zhǔn)答案,畢竟是自己的一些工作總結(jié)。各位讀者有更好的回答,也歡迎交流!

這里我要說一下,我用mysql只用過innodb存儲引擎,其他的引擎真沒用過。因此我的回答,都是基于innodb存儲引擎中的。

正文

問題1:為什么一定要設(shè)一個主鍵?

回答:因為你不設(shè)主鍵的情況下,innodb也會幫你生成一個隱藏列,作為自增主鍵。所以啦,反正都要生成一個主鍵,那你還不如自己指定一個主鍵,在有些情況下,就能顯式的用上主鍵索引,提高查詢效率!

問題2:主鍵是用自增還是UUID?

回答:肯定答自增啊。innodb 中的主鍵是聚簇索引。如果主鍵是自增的,那么每次插入新的記錄,記錄就會順序添加到當(dāng)前索引節(jié)點的后續(xù)位置,當(dāng)一頁寫滿,就會自動開辟一個新的頁。如果不是自增主鍵,那么可能會在中間插入,就會引發(fā)頁的分裂,產(chǎn)生很多表碎片!。

上面那句話看不懂沒事,大白話一句就是:用自增插入性能好!

另外,附一個測試表給你們,表名帶uuid的就是用uuid作為主鍵。大家看一下就知道性能差距了:

如上圖所示,當(dāng)主鍵是UUID的時候,插入時間更長,而且占用空間更大!

額,大家千萬不要忘了,當(dāng)你回答自增主鍵后,想一下《自增主鍵用完該怎么辦?》

ps:這個問題,你要是能把UUID講出合理的理由也行。

問題3:主鍵為什么不推薦有業(yè)務(wù)含義?

回答:有如下兩個原因

  • (1)因為任何有業(yè)務(wù)含義的列都有改變的可能性,主鍵一旦帶上了業(yè)務(wù)含義,那么主鍵就有可能發(fā)生變更。主鍵一旦發(fā)生變更,該數(shù)據(jù)在磁盤上的存儲位置就會發(fā)生變更,有可能會引發(fā)頁分裂,產(chǎn)生空間碎片。
  • (2)帶有業(yè)務(wù)含義的主鍵,不一定是順序自增的。那么就會導(dǎo)致數(shù)據(jù)的插入順序,并不能保證后面插入數(shù)據(jù)的主鍵一定比前面的數(shù)據(jù)大。如果出現(xiàn)了,后面插入數(shù)據(jù)的主鍵比前面的小,就有可能引發(fā)頁分裂,產(chǎn)生空間碎片。

問題4:表示枚舉的字段為什么不用enum類型?

回答:在工作中表示枚舉的字段,一般用tinyint類型。

那為什么不用enum類型呢?下面兩個原因

(1)ENUM類型的ORDER BY操作效率低,需要額外操作

(2)如果枚舉值是數(shù)值,有陷阱

舉個例子,表結(jié)構(gòu)如下

CREATE TABLE test (foobar ENUM('0', '1', '2'));

此時,你執(zhí)行語句

mysql> INSERT INTO test VALUES (1);

查詢出的結(jié)果為

foobar0

就產(chǎn)生了一個坑爹的結(jié)果。

插入語句應(yīng)該像下面這么寫,插入的才是1

mysql> INSERT INTO test VALUES (`1`);

問題5:貨幣字段用什么類型?

回答:如果貨幣單位是分,可以用Int類型。如果堅持用元,用Decimal。

千萬不要答float和double,因為float和double是以二進(jìn)制存儲的,所以有一定的誤差。

打個比方,你建一個列如下

CREATE TABLE `t` ( `price` float(10,2) DEFAULT NULL,) ENGINE=InnoDB DEFAULT CHARSET=utf8

然后insert給price列一個數(shù)據(jù)為1234567.23,你會發(fā)現(xiàn)顯示出來的數(shù)據(jù)變?yōu)?234567.25,精度失準(zhǔn)!

問題6:時間字段用什么類型?

回答:此題無固定答案,應(yīng)結(jié)合自己項目背景來答!把理由講清楚就行!

(1)varchar,如果用varchar類型來存時間,優(yōu)點在于顯示直觀。但是坑的地方也是挺多的。比如,插入的數(shù)據(jù)沒有校驗,你可能某天就發(fā)現(xiàn)一條數(shù)據(jù)為2013111的數(shù)據(jù),請問這是代表2013年1月11日,還是2013年11月1日?

其次,做時間比較運算,你需要用STR_TO_DATE等函數(shù)將其轉(zhuǎn)化為時間類型,你會發(fā)現(xiàn)這么寫是無法命中索引的。數(shù)據(jù)量一大,是個坑!

(2)timestamp,該類型是四個字節(jié)的整數(shù),它能表示的時間范圍為1970-01-01 08:00:01到2038-01-19 11:14:07。2038年以后的時間,是無法用timestamp類型存儲的。

但是它有一個優(yōu)勢,timestamp類型是帶有時區(qū)信息的。一旦你系統(tǒng)中的時區(qū)發(fā)生改變,例如你修改了時區(qū)

SET TIME_ZONE = "america/new_york";

你會發(fā)現(xiàn),項目中的該字段的值自己會發(fā)生變更。這個特性用來做一些國際化大項目,跨時區(qū)的應(yīng)用時,特別注意!

(3)datetime,datetime儲存占用8個字節(jié),它存儲的時間范圍為1000-01-01 00:00:00 ~ 9999-12-31 23:59:59。顯然,存儲時間范圍更大。但是它坑的地方在于,他存儲的是時間絕對值,不帶有時區(qū)信息。如果你改變數(shù)據(jù)庫的時區(qū),該項的值不會自己發(fā)生變更!

(4)bigint,也是8個字節(jié),自己維護(hù)一個時間戳,表示范圍比timestamp大多了,就是要自己維護(hù),不大方便。

問題7:為什么不直接存儲圖片、音頻、視頻等大容量內(nèi)容?

回答:我們在實際應(yīng)用中,都是用HDFS來存儲文件。然后mysql中,只存文件的存放路徑。mysql中有兩個字段類型被用來設(shè)計存放大容量文件,也就是text和blob類型。但是,我們在生產(chǎn)中,基本不用這兩個類型!

主要原因有如下兩點

  • (1)Mysql內(nèi)存臨時表不支持TEXT、BLOB這樣的大數(shù)據(jù)類型,如果查詢中包含這樣的數(shù)據(jù),在排序等操作時,就不能使用內(nèi)存臨時表,必須使用磁盤臨時表進(jìn)行。導(dǎo)致查詢效率緩慢
  • (2)binlog內(nèi)容太多。因為你數(shù)據(jù)內(nèi)容比較大,就會造成binlog內(nèi)容比較多。大家也知道,主從同步是靠binlog進(jìn)行同步,binlog太大了,就會導(dǎo)致主從同步效率問題!

因此,不推薦使用text和blob類型!

問題8:字段為什么要定義為NOT NULL?

回答:OK,這問題從兩個角度來答

(1)索引性能不好

Mysql難以優(yōu)化引用可空列查詢,它會使索引、索引統(tǒng)計和值更加復(fù)雜。可空列需要更多的存儲空間,還需要mysql內(nèi)部進(jìn)行特殊處理。可空列被索引后,每條記錄都需要一個額外的字節(jié),還能導(dǎo)致MYisam 中固定大小的索引變成可變大小的索引。 —— 出自《高性能mysql第二版》

(2)查詢會出現(xiàn)一些不可預(yù)料的結(jié)果

這里舉一個例子,大家就懂了。假設(shè),表結(jié)構(gòu)如下

create table table_2 ( `id` INT (11) NOT NULL, name varchar(20) NOT NULL)

表數(shù)據(jù)是這樣的

你執(zhí)行語句

select count(name) from table_2;

你會發(fā)現(xiàn)結(jié)果為2,但是實際上是有四條數(shù)據(jù)的!類似的查詢問題,其實有很多,不一一列舉。

記住,因為null列的存在,會出現(xiàn)很多出人意料的結(jié)果,從而浪費開發(fā)時間去排查Bug.

總結(jié)

以上是生活随笔為你收集整理的mysql datetime 后面带了很多0_面试官:MySQL 表设计要注意什么?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。