最近兩天作需求,是要將退款和退貨報表裏使用的臨時表改用固定表,html
本身建表時,如(只是舉例):mysql
CREATE TABLE tasks ( task_id INT UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INT UNSIGNED NOT NULL DEFAULT 0, task VARCHAR(100) NOT NULL, test_id INT UNSIGNED NOT NULL DEFAULT 0, date_added TIMESTAMP NOT NULL, date_completed TIMESTAMP, PRIMARY KEY (task_id), key parent_id(parent_id), key test_id (test_id ) )engine=INNODB;
像parent_id及test_id在連表查詢時,屢次出如今where的條件中,因此要給他們加上索引。sql
在此過程當中,我想了這麼幾個問題:爲何這裏要用key而不用index呢?臨時表有什麼特色,它是存放在內存中嗎?數據庫
問題1.mysql中index和key的區別?session
---這種問題其實也是stackoverflow裏的常見問題(http://stackoverflow.com/questions/1401572/what-are-differences-between-index-v-s-key-in-mysql)---post
key 是數據庫的物理結構,處於模型層面的,它包含兩層意義,一是約束(偏重於約束和規範數據庫的結構完整性),二是索引(輔助查詢用的)。包括primary key, unique key, foreign key 等。性能
->primary key 優化
兩個做用,一是約束做用(constraint),用來規範一個存儲主鍵和惟一性,但同時也在此key上創建了一個index;ui
->unique keyurl
兩個做用,一是約束做用(constraint),規範數據的惟一性,但同時也在這個key上創建了一個index;
->foreign key
兩個做用,一是約束做用(constraint),規範數據的引用完整性,但同時也在這個key上創建了一個index;
總結來講:MySQL中的key是同時具備constraint和index的意義。
MySQL requires every Key also be indexed, that's an implementation detail specific to MySQL to improve performance.
index是數據庫的物理結構,處於實現層面的,它只是輔助查詢的,它建立時會在另外的表空間(mysql中的innodb表空間)以一個相似目錄的結構存儲。索引要分類的話,分爲前綴索引、全文本索引等;所以,索引只是索引,它不會去約束索引的字段的行爲(那是key要作的事情)。
Mysql常見索引有:主鍵索引、惟一索引、普通索引、全文索引、組合索引。
問題2.mysql中內存表和臨時表的區別?
內存表:
1. 參數控制:max_heap_table_size=1024M。 2. 到達上線後報錯,因此在同一時間須要足夠的內存。 3. 表定義保存在磁盤上,數據和索引保存在內存裏面。 4. 不能包含TEXT,BLOB等字段。 ------------------------------------------ 5.多個session,建立表的名字不能同樣 6. 一個session建立會話後,對其餘session也是可見的 7. data目錄下只有tmp_memory.frm ,表結構放在磁盤上,數據放在內存中 8. mysql 重啓或者關閉後內存表裏的數據會丟失,可是表結構仍然存在 9. 能夠建立索引,刪除索引,支持惟一索引 10. 不影響主備,主庫上插入的數據,備庫也能夠查到 11. show tables 看獲得表
使用內存表需注意:
-> 內存表須要本身delete數據或者drop表;須要drop權限,這點比較危險
->內存表的表結構是保存在磁盤上的,若是多個session使用同一個表名,會存在衝突;若是不須要使用表名,若是使用一次都須要建立表結構,到時候會有不少小文件存在,不利於db的維護,dba清理表也有風險;
臨時表:
1. 參數控制:tmp_table_size=1024M。 2. 到達上線後建立文件在磁盤上。 3. 表定義和數據都在內存裏。 4. 能夠包含TEXT, BLOB等字段。 ---------------------- 5. 建立的表的名字能夠同樣 6. 表結構和數據都放在內存中 7. 會話消失表結構和數據都消失 8. 能夠建立索引,刪除索引 9. 主庫建立的表,備庫查不到, 10. show tables 看不到表
另外:臨時表和內存表的ENGINE 不一樣,臨時表默認的是MyISAM,而內存表是MEMORY
我想以前用臨時表的考慮主要是下面兩個特色:
-> 臨時表是會話級別的,即便多個session建立的表名同樣,都相互不影響
-> 會話消失,全部的都消失,這點很不利於應用排查問題
->不管內存表仍是臨時表都須要消耗額外的內存空間,雖然db端能夠忍受,可是不太可控;
->DB端還有這個參數:max_tmp_tables 一個客戶能同時保持打開的臨時表的最大數量,這個值默認32,能夠根據須要調整此值
參考文章:mysql的內存表和臨時表
問題3.MySQL單列索引和聯合索引
有同事小夥伴說,根據須要與否,你能夠考慮下聯合索引。
「若是你對索引的理解不夠,很常見的一個錯誤就是,爲每一個列穿件獨立的多音,或者按照錯誤的順序建立多列索引。」
談到索引策略,不少聽到的諸如「把where條件裏的列都建上索引」這樣模糊的建議是很是錯誤的。這種方法最好的狀況也只能是「一星」索引,
要實現真正更優的索引,得花精力優化索引列的順序,或者建立一個全覆蓋的索引。
---注:在《高性能MySQL》中文第三版提到了索引的評估:三星評估(three-star system)
索引將相關的記錄放到一塊兒得到一星;
若是索引中的數據順序和查找中的排列順序一致得到兩星;
若是索引中的列包含了查詢中須要的所有列則得到三星;
最近幾天看《高性能MySQL》仍是收穫挺大,勤看書仍是頗有必要的,同時和實踐結合起來!
後續再來補充,若有我理解不正確的地方,但願有人能提出!