程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL建表規范與常見問題,mysql建常見問題

MySQL建表規范與常見問題,mysql建常見問題

編輯:MySQL綜合教程

MySQL建表規范與常見問題,mysql建常見問題


 

一、 表設計

二、 索引

三、 SQL語句

四、 散表

五、 其他

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

FAQ

1-1.庫名、表名、字段名必須使用小寫字母,“_”分割。

a)MySQL有配置參數lower_case_table_names,不可動態更改,linux系統默認為0,即庫表名以實際情況存儲,大小寫敏感。如果是1,以小寫存儲,大小寫不敏感。如果是2,以實際情況存儲,但以小寫比較。

b) 如果大小寫混合用,可能存在abc,Abc,ABC等多個表共存,容易導致混亂。

c) 字段名顯示區分大小寫,但實際使用不區分,即不可以建立兩個名字一樣但大小寫不一樣的字段。

d) 為了統一規范, 庫名、表名、字段名使用小寫字母。

 

1-2.庫名、表名、字段名必須不超過12個字符。

庫名、表名、字段名支持最多64個字符,但為了統一規范、易於辨識以及減少傳輸量,必須不超過12字符。

 

1-3.庫名、表名、字段名見名知意,建議使用名詞而不是動詞。

a) 用戶評論可用表名usercomment或者comment。

b) 庫表是一種客觀存在的事物,一種對象,所以建議使用名詞。

 

1-4.建議使用InnoDB存儲引擎。

a) 5.5以後的默認引擘,支持事務,行級鎖,更好的恢復性,高並發下性能更好,對多核,大內存,ssd等硬件支持更好。

b) 具體比較可見附件的官方白皮書。

 

1-5.存儲精確浮點數必須使用DECIMAL替代FLOAT和DOUBLE。

a) mysql中的數值類型(不包括整型):
    IEEE754浮點數:float  (單精度) , double  或real  (雙精度)
    定點數: decimal或 numeric
   單精度浮點數的有效數字二進制是24位,按十進制來說,是8位;雙精度浮點數的有效數字二進制是53位,按十進制來說,是16 位
   一個實數的有效數字超過8位,用單精度浮點數來表示的話,就會產生誤差!同樣,如果一個實數的有效數字超過16位,用雙精度浮點數來表示,也會產生誤差
b)IEEE754標准的計算機浮點數,在內部是用二進制表示的,但在將一個十進制數轉換為二進制浮點數時,也會造成誤差,原因是不是所有的數都能轉換成有限長度的二進制數。
   即一個二進制可以准確轉換成十進制,但一個帶小數的十進制不一定能夠准確地用二進制來表示。

實例:
drop table if exists t;

create table t(value float(10,2));

insert into t values(131072.67),(131072.68);

select  value  from t;

+-----------+

|value    |

+-----------+

| 131072.67 |

| 131072.69 |

+-----------+

 

1-6.建議使用UNSIGNED存儲非負數值。

同樣的字節數,存儲的數值范圍更大。如tinyint 有符號為 -128-127,無符號為0-255

 

1-7. 如何使用INT UNSIGNED存儲ip?

使用INTUNSIGNED而不是char(15)來存儲ipv4地址,通過MySQL函數inet_ntoa和inet_aton來進行轉化。Ipv6地址目前沒有轉化函數,需要使用DECIMAL或者兩個bigINT來存儲。例如:

SELECT INET_ATON('209.207.224.40');

3520061480

SELECT INET_NTOA(3520061480);

209.207.224.40

 

1-8. INT[M],M值代表什麼含義?

注意數值類型括號後面的數字只是表示寬度而跟存儲范圍沒有關系,比如INT(3)默認顯示3位,空格補齊,超出時正常顯示,Python、java客戶端等不具備這個功能。

 

1-10.不建議使用ENUM、SET類型,使用TINYINT來代替。

a)ENUM,有三個問題:添加新的值要做DDL,默認值問題(將一個非法值插入ENUM(也就是說,允許的值列之外的字符串),將插入空字符串以作為特殊錯誤值),索引值問題(插入數字實際是插入索引對應的值)

實例:

drop table if exists t;

create table t(sex enum('0','1'));

insert into t values(1);

insert into t values('3');

select * from t;

+------+

| sex  |

+------+

| 0    |

|     |

+------+

2 rows in set (0.00 sec)

 

1-11.盡可能不使用TEXT、BLOB類型。

a) 索引排序問題,只能使用max_sort_length的長度或者手工指定ORDER BY SUBSTRING(column,length)的長度來排序

b) Memory引擘不支持text,blog類型,會在磁盤上生成臨時表

c) 可能浪費更多的空間

d) 可能無法使用adaptive hash index

e) 導致使用where沒有索引的語句變慢

 

1-13. VARCHAR中會產生額外存儲嗎?

VARCHAR(M),如果M<256時會使用一個字節來存儲長度,如果M>=256則使用兩個字節來存儲長度。

 

1-14.表字符集選擇UTF8。

a) 使用utf8字符集,如果是漢字,占3個字節,但ASCII碼字符還是1個字節。
b) 統一,不會有轉換產生亂碼風險
c) 其他地區的用戶(美國、印度、台灣)無需安裝簡體中文支持,就能正常看您的文字,並且不會出現亂碼
d)ISO-8859-1編碼(latin1)使用了單字節內的所有空間,在支持ISO-8859-1的系統中傳輸和存儲其他任何編碼的字節流都不會被拋棄。即把其他任何編碼的字節流當作ISO-8859-1編碼看待都沒有問題,保存的是原封不動的字節流。

 

1-15.使用VARBINARY存儲變長字符串。

二進制字節流,不存在編碼問題

 

1-18. 為什麼建議使用TIMESTAMP來存儲時間而不是DATETIME?

DATETIME和TIMESTAMP都是精確到秒,優先選擇TIMESTAMP,因為TIMESTAMP只有4個字節,而DATETIME8個字節。同時TIMESTAMP具有自動賦值以及自動更新的特性。

如何使用TIMESTAMP的自動賦值屬性?

a)  將當前時間作為ts的默認值:ts TIMESTAMP DEFAULTCURRENT_TIMESTAMP。

b)  當行更新時,更新ts的值:ts TIMESTAMP DEFAULT 0 ONUPDATE CURRENT_TIMESTAMP。

c)  可以將1和2結合起來:ts TIMESTAMP DEFAULTCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。

 

1-19.建議字段定義為NOT NULL。

a)如果null字段被索引,需要額外的1字節

b)使索引,索引統計,值的比較變得更復雜

c)可用0,''代替

d)如果是索引字段,一定要定義為not null

 

1-21.禁止在數據庫中使用VARBINARY、BLOB存儲圖片、文件等。

采用分布式文件系統更高效

 

2. 為什麼MySQL的性能依賴於索引?

MySQL的查詢速度依賴良好的索引設計,因此索引對於高性能至關重要。合理的索引會加快查詢速度(包括UPDATE和DELETE的速度,MySQL會將包含該行的page加載到內存中,然後進行UPDATE或者DELETE操作),不合理的索引會降低速度。

MySQL索引查找類似於新華字典的拼音和部首查找,當拼音和部首索引不存在時,只能通過一頁一頁的翻頁來查找。當MySQL查詢不能使用索引時,MySQL會進行全表掃描,會消耗大量的IO。

 

2-5. 為什麼一張表中不能存在過多的索引?

InnoDB的secondaryindex使用b+tree來存儲,因此在UPDATE、DELETE、INSERT的時候需要對b+tree進行調整,過多的索引會減慢更新的速度。

 

2-11. EXPLAIN語句

EXPLAIN語句(在MySQL客戶端中執行)可以獲得MySQL如何執行SELECT語句的信息。通過對SELECT語句執行EXPLAIN,可以知曉MySQL執行該SELECT語句時是否使用了索引、全表掃描、臨時表、排序等信息。盡量避免MySQL進行全表掃描、使用臨時表、排序等。詳見官方文檔。

 

2-13.不建議使用%前綴模糊查詢,例如LIKE “%weibo”。

會導致全表掃描

2-14. 如何對長度大於50的VARCHAR字段建立索引?

下面的表增加一列url_crc32,然後對url_crc32建立索引,減少索引字段的長度,提高效率。

  • CREATE TABLE url(

       ……

       url VARCHAR(255) NOT NULL DEFAULT 0,
       url_crc32INT UNSIGNED NOT NULL DEFAULT 0,

       ……

       index idx_url(url_crc32)

    )

 

2-16. 什麼是覆蓋索引?

InnoDB 存儲引擎中,secondaryindex(非主鍵索引)中沒有直接存儲行地址,存儲主鍵值。如果用戶需要查詢secondaryindex中所不包含的數據列時,需要先通過secondaryindex查找到主鍵值,然後再通過主鍵查詢到其他數據列,因此需要查詢兩次。

覆蓋索引的概念就是查詢可以通過在一個索引中完成,覆蓋索引效率會比較高,主鍵查詢是天然的覆蓋索引。

合理的創建索引以及合理的使用查詢語句,當使用到覆蓋索引時可以獲得性能提升。

比如SELECT email,uid FROM user_email WHEREuid=xx,如果uid不是主鍵,適當時候可以將索引添加為index(uid,email),以獲得性能提升。

 

3-3.UPDATE、DELETE語句不使用LIMIT。

a) 可能導致主從數據不一致

b) 會記錄到錯誤日志,導致日志占用大量空間

3-4. 為什麼需要避免MySQL進行隱式類型轉化?

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved