資料庫操作是當今 web 應用程式中的主要瓶頸。 不僅是 dba(資料庫管理員)需要為各種效能問題操心,程式設計師為做出準確的結構化表,優化查詢效能和編寫更優**,也要費盡心思。 在本文中,我列出了一些針對程式設計師的 mysql 優化技術。
在我們開始學習之前,我補充一點:你可以在 envato market 上找到大量的 mysql 指令碼和實用程式。
大部分mysql伺服器都有查詢快取功能。這是提高效能的最有效的方法之一,這是由資料庫引擎私下處理的。當同乙個查詢被多次執行,結果會直接從快取裡提取,這樣速度就很快。
主要的問題是,這對程式設計師來說太簡單了,不容易看到,我們很多人都容易忽略。我們實際上是可以組織查詢快取執行任務的。
// query cache does
not
work
$r = mysql_query(
"select username from user where signup_date >= curdate()"
);
// query cache works!
$today =
date
(
"y-m-d"
);
$r = mysql_query(
"select username from user where signup_date >= '$today'"
);
查詢快取在第一行不執行的原因在於curdte()功能的使用。這適用於所有的非確定性功能,就像now()和rand()等等。因為功能返回的結果是可變的。mysql決定禁用查詢器的查詢快取。我們所需要做的是通過新增一額外一行php,在查詢前阻止它發生。
現在它只會從表2裡面掃瞄9和16行,而非掃瞄7883行。經驗法則是乘以所有「行」那一欄的數字,你的查詢效能會跟結果數字成比例的。
有時當你查表時,你已經知道你正在查詢的結果只有一行。你可能正在獲取唯一記錄,或者你可能只是查詢是否存在滿足你的where子句條件的記錄。
在這種情況下,將limit 1新增到查詢條件中可以提高效能。這樣,資料庫引擎將在找到剛剛第乙個記錄之後停止掃瞄記錄,而不是遍歷整個表或索引。
1
2
3
4
5
6
7
8
$r = mysql_query(
"select * from user where state = 'alabama'"
);
if (mysql_num_rows($r) > 0)
$r = mysql_query(
"select 1 from user where state = 'alabama' limit 1"
);
if (mysql_num_rows($r) > 0)
索引不僅僅是為了主鍵或唯一鍵。如果你會在你的表中按照任何列搜尋,你就都應該索引它們。
如果你的應用程式包含許多連線查詢, 你需要確保連線的字段在兩張表上都建立了索引。 這會影響mysql如何內部優化連線操作。
此外,被連線的字段,需要使用同樣型別。例如, 如果你使用乙個decimal欄位, 連線另一張表的int欄位, mysql將無法使用至少乙個索引。 即使字元編碼也需要使用相同的字元型別。
1
2
3
$r = mysql_query(
"select company_name from users
left join companies on (users.state = companies.state)
where users.id = $user_id"
);
起初這是乙個聽起來挺酷的技巧, 讓許多菜鳥程式設計師陷入了這個陷阱。但你可能不知道,一旦你開始在查詢中使用它,你建立了非常可怕的查詢瓶頸。
如果你真的需要對結果隨機排序, 這有乙個更好的方法。補充一些額外**,你將可以防止當資料成指數級增長時造成的瓶頸。關鍵問題是,mysql必須在排序之前對錶中的每一行執行rand()操作(這需要處理能力),並且僅僅給出一行。
1
2
3
4
5
$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"
);
所以挑選乙個小於結果數的隨機數,並將其用作limit子句中的偏移量。
從資料表中讀取的資料越多,查詢操作速度就越慢。它增加了磁碟操作所需的時間。此外,當資料庫伺服器與web伺服器分開時,由於必須在伺服器之間傳輸資料,將會有更長的網路延遲。
這是乙個好習慣:當你使用select語句時總是指定你需要的列。
1
2
3
4
5
6
$r
= mysql_query(
"select * from user where user_id = 1"
);
$d
= mysql_fetch_assoc(
$r
);
echo
"welcome "
;
$r
= mysql_query(
"select username from user where user_id = 1"
);
$d
= mysql_fetch_assoc(
$r
);
echo
"welcome "
;
在每個以id列為primary key的資料表中,優先選擇auto_increment或者int。 也可以優選使用unsigned,因為該值不能為負的。
即使你擁有乙個具有唯一使用者名字段的使用者表,也不要將其作為主鍵。 varchar欄位作為主鍵(檢索)速度較慢。通過內部id引用所有的使用者資料,你的**中將更加結構化。
有些後台操作是由mysql引擎本身完成的,它在內部使用主鍵字段。當資料庫設定越複雜(集群,分割槽等…),這就變得更加重要了。
這個規則的乙個可能的例外是「關聯表」,用於兩個表之間的多對多型別的關聯。例如,「posts_tags」表中包含兩列:post_id,tag_id,用於儲存表名為「post」和「tags」的兩個表之間的關係。這些表可以具有包含兩個id欄位的primary鍵。
enum列舉型別是非常快速和緊湊的。在內部它們像tinyint一樣儲存,但它們可以包含和顯示字串值。這使他們成為某些領域的完美候選。
如果有乙個欄位只包含幾種不同的值,請使用enum而不是varchar。例如,它可以是名為「status」的列,並且只包含諸如「active」,「inactive」,「pending」,「expired」等的值…
關於如何重構你的資料表,甚至有一種方法是可以從mysql本身得到「建議」。 當你有乙個varchar欄位,它實際上建議你將該列型別更改為enum。這通過呼叫procedure analyze()來完成。
procedure analyse() 將使用mysql分析列結構和表中的實際資料,為你提供一些建議。它只有在資料表中有實際資料時才有用,因為這在分析決策時很重要。
例如,如果你建立了乙個int型別的主鍵,但沒有太多行,mysql則可能建議您改用mediumint。或者如果你使用varchar欄位,如果表裡只有很少的取值,你可能會得到乙個建議是將其轉換為enum。
你也可以在其中乙個表檢視中單擊phpmyadmin中的「建議表結構」鏈結來執行此操作。
請記住,這些只是建議。 如果你的資料表變得越來越大,他們甚至可能不是正確的建議。至於如何修改最終是你來決定。
MySQL效能優化的21個最佳實踐
今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應用尤其明顯。關於資料庫的效能,這並不只是dba才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時 尤其是查表時的sql 具體可以參考 inet aton和inet ntoa 15.固定長度...
最佳實踐React效能優化
1 基本使用 使用方法 import react,from react import from utils const loadinghome dynamic import components home const loadinguser dynamic import components use...
JS最佳實踐 效能優化
首先,由於js是一種解釋型語言,執行速度要比編譯型語言慢得多。注 chrome是第一款內建優化引擎,將js編譯成本地 的瀏覽器,其它瀏覽器也陸續實現了js的編譯過程。但是,即使到了編譯執行js的新階段,仍然會存在低效率的 以下總結一些可以改進 的整體效能的方法。記住一點,隨著作用域中的作用域數量的增...