近期因爲複習了一下mysql的內容,有些心得。隨手講其中一部分知識,都是一些煙哥本身平時工做的總結以及經驗。你們看完,其實能避開不少坑。並且不少問題,都是面試中實打實會問到的!
好比
html
OK,具體有下面這些問題mysql
其實上面這些問題,我最先想法是,每一個問題均可以囉嗦出一篇文章。後來因爲良心發現,煙哥就決定用一篇文章將這些問題都講明白。
固然,我給的回答可能並不是標準答案,畢竟是本身的一些工做總結。各位讀者有更好的回答,也歡迎交流!面試
這裏我要說一下,我用mysql只用過innodb
存儲引擎,其餘的引擎真沒用過。所以個人回答,都是基於innodb
存儲引擎中的。sql
問題1:爲何必定要設一個主鍵?
回答:由於你不設主鍵的狀況下,innodb也會幫你生成一個隱藏列,做爲自增主鍵。因此啦,反正都要生成一個主鍵,那你還不如本身指定一個主鍵,在有些狀況下,就能顯式的用上主鍵索引,提升查詢效率!數據庫
問題2:主鍵是用自增仍是UUID?
回答:確定答自增啊。innodb 中的主鍵是聚簇索引。若是主鍵是自增的,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。若是不是自增主鍵,那麼可能會在中間插入,就會引起頁的分裂,產生不少表碎片!。
上面那句話看不懂沒事,大白話一句就是:用自增插入性能好!
另外,附一個測試表給大家,表名帶uuid的就是用uuid做爲主鍵。你們看一下就知道性能差距了:
函數
如上圖所示,當主鍵是UUID的時候,插入時間更長,並且佔用空間更大!性能
額,你們千萬不要忘了,當你回答自增主鍵後,想一下《自增主鍵用完該怎麼辦?》測試
ps
:這個問題,你要是能把UUID
講出合理的理由也行。大數據
問題3:主鍵爲何不推薦有業務含義?
回答:有以下兩個緣由優化
問題4:表示枚舉的字段爲何不用enum類型?
回答:在工做中表示枚舉的字段,通常用tinyint
類型。
那爲何不用enum類型呢?下面兩個緣由
(1)ENUM類型的ORDER BY操做效率低,須要額外操做
(2)若是枚舉值是數值,有陷阱
舉個例子,表結構以下
CREATE TABLE test (foobar ENUM('0', '1', '2'));
此時,你執行語句
mysql> INSERT INTO test VALUES (1);
查詢出的結果爲
就產生了一個坑爹的結果。
插入語句應該像下面這麼寫,插入的纔是1
mysql> INSERT INTO test VALUES (`1`);
問題5:貨幣字段用什麼類型?
回答:若是貨幣單位是分,能夠用Int
類型。若是堅持用元,用Decimal
。
千萬不要答float
和double
,由於float和double是以二進制存儲的,因此有必定的偏差。
打個比方,你建一個列以下
CREATE TABLE `t` ( `price` float(10,2) DEFAULT NULL, ) ENGINE=InnoDB DEFAULT CHARSET=utf8
而後insert給price列一個數據爲1234567.23
,你會發現顯示出來的數據變爲1234567.25
,精度失準!
問題6:時間字段用什麼類型?
回答:此題無固定答案,應結合本身項目背景來答!把理由講清楚就行!
(1)varchar
,若是用varchar類型來存時間,優勢在於顯示直觀。可是坑的地方也是挺多的。好比,插入的數據沒有校驗,你可能某天就發現一條數據爲2013111
的數據,請問這是表明2013年1月11日,仍是2013年11月1日?
其次,作時間比較運算,你須要用STR_TO_DATE
等函數將其轉化爲時間類型,你會發現這麼寫是沒法命中索引的。數據量一大,是個坑!
(2)timestamp
,該類型是四個字節的整數,它能表示的時間範圍爲1970-01-01 08:00:01到2038-01-19 11:14:07。2038年之後的時間,是沒法用timestamp
類型存儲的。
可是它有一個優點,timestamp
類型是帶有時區信息的。一旦你係統中的時區發生改變,例如你修改了時區
SET TIME_ZONE = "america/new_york";
你會發現,項目中的該字段的值本身會發生變動。這個特性用來作一些國際化大項目,跨時區的應用時,特別注意!
(3)datetime
,datetime儲存佔用8個字節,它存儲的時間範圍爲1000-01-01 00:00:00 ~ 9999-12-31 23:59:59。顯然,存儲時間範圍更大。可是它坑的地方在於,他存儲的是時間絕對值,不帶有時區信息。若是你改變數據庫的時區,該項的值不會本身發生變動!
(4)bigint
,也是8個字節,本身維護一個時間戳,表示範圍比timestamp
大多了,就是要本身維護,不大方便。
問題7:爲何不直接存儲圖片、音頻、視頻等大容量內容?
回答:咱們在實際應用中,都是用HDFS
來存儲文件。而後mysql中,只存文件的存放路徑。mysql中有兩個字段類型被用來設計存放大容量文件,也就是text
和blob
類型。可是,咱們在生產中,基本不用這兩個類型!
主要緣由有以下兩點
binlog
內容太多。由於你數據內容比較大,就會形成binlog
內容比較多。你們也知道,主從同步是靠binlog
進行同步,binlog
太大了,就會致使主從同步效率問題!所以,不推薦使用text
和blob
類型!
問題8:字段爲何要定義爲NOT NULL?
回答:OK,這問題從兩個角度來答
(1)索引性能很差
Mysql難以優化引用可空列查詢,它會使索引、索引統計和值更加複雜。可空列須要更多的存儲空間,還須要mysql內部進行特殊處理。可空列被索引後,每條記錄都須要一個額外的字節,還能致使MYisam 中固定大小的索引變成可變大小的索引。
—— 出自《高性能mysql第二版》
(2)查詢會出現一些不可預料的結果
這裏舉一個例子,你們就懂了。假設,表結構以下
create table table_2 ( `id` INT (11) NOT NULL, name varchar(20) NOT NULL )
表數據是這樣的
id | name |
---|---|
1 | 孤獨煙 |
3 |
|
5 | 肥朝 |
7 |
|
你執行語句
select count(name) from table_2;
你會發現結果爲2,可是其實是有四條數據的!相似的查詢問題,其實有不少,不一一列舉。
記住,由於null列的存在,會出現不少出人意料的結果,從而浪費開發時間去排查Bug.
但願你們有所收穫吧!