Mysql 性能优化20个原则(2)
5. 在Join表的時候使用相當類型的例,并將其索引
如果你的應用程序有很多 JOIN 查詢,你應該確認兩個表中Join的字段是被建過索引的。這樣,MySQL內(nèi)部會啟動為你優(yōu)化Join的SQL語句的機制。
而且,這些被用來Join的字段,應該是相同的類型的。例如:如果你要把 DECIMAL 字段和一個 INT 字段Join在一起,MySQL就無法使用它們的索引。對于那些STRING類型,還需要有相同的字符集才行。(兩個表的字符集有可能不一樣)
| 1 2 3 4 5 6 | // 在state中查找company $r?= mysql_query("SELECT company_name FROM users ????LEFT JOIN companies ON (users.state = companies.state) ????WHERE users.id =$user_id"); // 兩個 state 字段應該是被建過索引的,而且應該是相當?shù)念愋?#xff0c;相同的字符集。 |
6. 千萬不要 ORDER BY RAND()
想打亂返回的數(shù)據(jù)行?隨機挑一個數(shù)據(jù)?真不知道誰發(fā)明了這種用法,但很多新手很喜歡這樣用。但你確不了解這樣做有多么可怕的性能問題。
如果你真的想把返回的數(shù)據(jù)行打亂了,你有N種方法可以達到這個目的。這樣使用只讓你的數(shù)據(jù)庫的性能呈指數(shù)級的下降。這里的問題是:MySQL會不得不去執(zhí)行RAND()函數(shù)(很耗CPU時間),而且這是為了每一行記錄去記行,然后再對其排序。就算是你用了Limit 1也無濟于事(因為要排序)
下面的示例是隨機挑一條記錄
| 1 2 3 4 5 6 7 8 9 | // 千萬不要這樣做: $r?= mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1"); // 這要會更好: $r?= mysql_query("SELECT count(*) FROM user"); $d?= mysql_fetch_row($r); $rand?= mt_rand(0,$d[0] - 1); $r?= mysql_query("SELECT username FROM user LIMIT $rand, 1"); |
7. 避免 SELECT *
從數(shù)據(jù)庫里讀出越多的數(shù)據(jù),那么查詢就會變得越慢。并且,如果你的數(shù)據(jù)庫服務器和WEB服務器是兩臺獨立的服務器的話,這還會增加網(wǎng)絡傳輸?shù)呢撦d。
所以,你應該養(yǎng)成一個需要什么就取什么的好的習慣。
| 1 2 3 4 5 6 7 8 9 | // 不推薦 $r?= mysql_query("SELECT * FROM user WHERE user_id = 1"); $d?= mysql_fetch_assoc($r); echo?"Welcome {$d['username']}"; // 推薦 $r?= mysql_query("SELECT username FROM user WHERE user_id = 1"); $d?= mysql_fetch_assoc($r); echo?"Welcome {$d['username']}"; |
8. 永遠為每張表設置一個ID
我們應該為數(shù)據(jù)庫里的每張表都設置一個ID做為其主鍵,而且最好的是一個INT型的(推薦使用UNSIGNED),并設置上自動增加的AUTO_INCREMENT標志。
就算是你 users 表有一個主鍵叫 “email”的字段,你也別讓它成為主鍵。使用 VARCHAR 類型來當主鍵會使用得性能下降。另外,在你的程序中,你應該使用表的ID來構(gòu)造你的數(shù)據(jù)結(jié)構(gòu)。
而且,在MySQL數(shù)據(jù)引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設置變得非常重要,比如,集群,分區(qū)……
在這里,只有一個情況是例外,那就是“關(guān)聯(lián)表”的“外鍵”,也就是說,這個表的主鍵,通過若干個別的表的主鍵構(gòu)成。我們把這個情況叫做“外鍵”。比如:有一個“學生表”有學生的ID,有一個“課程表”有課程ID,那么,“成績表”就是“關(guān)聯(lián)表”了,其關(guān)聯(lián)了學生表和課程表,在成績表中,學生ID和課程ID叫“外鍵”其共同組成主鍵。
9. 使用 ENUM 而不是 VARCHAR
ENUM?類型是非??旌途o湊的。在實際上,其保存的是 TINYINT,但其外表上顯示為字符串。這樣一來,用這個字段來做一些選項列表變得相當?shù)耐昝馈?/p>
如果你有一個字段,比如“性別”,“國家”,“民族”,“狀態(tài)”或“部門”,你知道這些字段的取值是有限而且固定的,那么,你應該使用 ENUM 而不是 VARCHAR。
MySQL也有一個“建議”(見第十條)告訴你怎么去重新組織你的表結(jié)構(gòu)。當你有一個 VARCHAR 字段時,這個建議會告訴你把其改成 ENUM 類型。使用 PROCEDURE ANALYSE() 你可以得到相關(guān)的建議。
10. 從 PROCEDURE ANALYSE() 取得建議
PROCEDURE ANALYSE()?會讓 MySQL 幫你去分析你的字段和其實際的數(shù)據(jù),并會給你一些有用的建議。只有表中有實際的數(shù)據(jù),這些建議才會變得有用,因為要做一些大的決定是需要有數(shù)據(jù)作為基礎(chǔ)的。
例如,如果你創(chuàng)建了一個 INT 字段作為你的主鍵,然而并沒有太多的數(shù)據(jù),那么,PROCEDURE ANALYSE()會建議你把這個字段的類型改成 MEDIUMINT ?;蚴悄闶褂昧艘粋€ VARCHAR 字段,因為數(shù)據(jù)不多,你可能會得到一個讓你把它改成 ENUM 的建議。這些建議,都是可能因為數(shù)據(jù)不夠多,所以決策做得就不夠準。
在phpmyadmin里,你可以在查看表時,點擊 “Propose table structure” 來查看這些建議
一定要注意,這些只是建議,只有當你的表里的數(shù)據(jù)越來越多時,這些建議才會變得準確。一定要記住,你才是最終做決定的人。
11. 盡可能的使用 NOT NULL
除非你有一個很特別的原因去使用 NULL 值,你應該總是讓你的字段保持 NOT NULL。這看起來好像有點爭議,請往下看。
首先,問問你自己“Empty”和“NULL”有多大的區(qū)別(如果是INT,那就是0和NULL)?如果你覺得它們之間沒有什么區(qū)別,那么你就不要使用NULL。(你知道嗎?在?Oracle?里,NULL 和 Empty 的字符串是一樣的!)
不要以為 NULL 不需要空間,其需要額外的空間,并且,在你進行比較的時候,你的程序會更復雜。 當然,這里并不是說你就不能使用NULL了,現(xiàn)實情況是很復雜的,依然會有些情況下,你需要使用NULL值。
下面摘自MySQL自己的文檔:
“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”
轉(zhuǎn)載于:https://www.cnblogs.com/mafeng/p/6824677.html
總結(jié)
以上是生活随笔為你收集整理的Mysql 性能优化20个原则(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 物联网传感技术——光纤传感器
- 下一篇: 如何把电脑的计算机固定在桌面上,如何将W