1.count(1)和count(primary_key) 優於 count(*)
很多人為了統計記錄條數,就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他們認為這樣效能更好,其實這是乙個誤區。對於有些場景,這樣做可能性能會更差,應為資料庫對 count(*) 計數操作做了一些特別的優化。
2.count(column) 和 count(*) 是一樣的
這個誤區甚至在很多的資深工程師或者是 dba 中都普遍存在,很多人都會認為這是理所當然的。實際上,count(column) 和 count(*) 是乙個完全不一樣的操作,所代表的意義也完全不一樣。
count(column) 是表示結果集中有多少個column欄位不為空的記錄。
count(*) 是表示整個結果集有多少條記錄。
3.select a,b from … 比 select a,b,c from … 可以讓資料庫訪問更少的資料量
這個誤區主要存在於大量的開發人員中,主要原因是對資料庫的儲存原理不是太了解。
實際上,大多數關係型資料庫都是按照行(row)的方式儲存,而資料訪問操作都是以乙個固定大小的io單元(被稱作 block 或者 page)為單位,一般為4kb,8kb… 大多數時候,每個io單元中儲存了多行,每行都是儲存了該行的所有字段(lob等特殊型別字段除外)。
所以,我們是取乙個字段還是多個字段,實際上資料庫在表中需要訪問的資料量其實是一樣的。
4.盡量少排序
排序操作會消耗較多的 cpu 資源,所以減少排序可以在快取命中率高等 io 能力足夠的場景下會較大影響 sql 的響應時間。
對於mysql來說,減少排序有多種辦法,比如:
上面誤區中提到的通過利用索引來排序的方式進行優化
減少參與排序的記錄條數
非必要不對資料進行排序
5.盡量避免 select *
很多人看到這一點後覺得比較難理解,上面不是在誤區中剛剛說 select 子句中字段的多少並不會影響到讀取的資料嗎?
是的,大多數時候並不會影響到 io 量,但是當我們還存在 order by 操作的時候,select 子句中的字段多少會在很大程度上影響到我們的排序效率,這一點可以通過我之前一篇介紹 mysql order by 的實現分析的文章中有較為詳細的介紹。
此外,上面誤區中不是也說了,只是大多數時候是不會影響到 io 量,當我們的查詢結果僅僅只需要在索引中就能找到的時候,還是會極大減少 io 量的。
6.拆分大的 delete 或 insert 語句
apache 會有很多的子程序或執行緒。所以,其工作起來相當有效率,而我們的伺服器也不希望有太多的子程序,執行緒和資料庫鏈結,這是極大的佔伺服器資源的事情,尤其是記憶體。
如果你把你的表鎖上一段時間,比如30秒鐘,那麼對於乙個有很高訪問量的站點來說,這30秒所積累的訪問程序/執行緒,資料庫鏈結,開啟的檔案數,可能不僅僅會讓你泊web服務crash,還可能會讓你的整台伺服器馬上掛了。
while (1)1.盡量避免在 where 子句中對字段進行表示式操作//每次都要休息一會兒
usleep(
50000);
}
select id from uinfo_jifen where jifen/60 > 10000;
優化後:
select id from uinfo_jifen where jifen>600000;
2.應盡量避免在where子句中對字段進行函式操作,這將導致mysql放棄使用索引
select uid from imid where datediff(create_time,'2011-11-22')=0
優化後select uid from imid where create_time> ='2011-11-21『 and create_time
8.join的優化
如果你的應用程式有很多 join 查詢,你應該確認兩個表中join的字段是被建過索引的。這樣,mysql內部會啟動為你優化join的sql語句的機制。而且,這些被用來join的字段,應該是相同的型別的。例如:如果你要把 decimal 欄位和乙個 int 欄位join在一起,mysql就無法使用它們的索引。對於那些string型別,還需要有相同的字符集才行。(兩個表的字符集有可能不一樣)。
9.索引的優化
1.mysql只有對以下操作符才使用索引:,>=,between,in,以及某些時候的like。
2.盡量不要寫!=或者<>的sql,用between或》 and 《代替,否則可能用不到索引
3.order by 、group by 、distinct 最好在需要這個列上建立索引,利於索引排序
4.盡量利用mysql索引排序
5.沒辦法的情況下,使用強制索引force index(index_name)
6.盡量避勉innodb用非常大尺寸的字段作為主鍵
7.較頻繁的作為查詢條件的字段應該建立索引;
8.選擇性高的字段比較適合建立索引;
9.作為表關聯字段一般都需要創索引.
10.更新非常頻繁的字段不適合建立索引;
11.不會出現在 where 子句中的字段不該建立索引.
12.選擇性太低的字段不適合單獨建立索引
1.盡可能的使用 not null
除非你有乙個很特別的原因去使用 null 值,你應該總是讓你的字段保持 not null。
不要以為 null 不需要空間,其需要額外的空間,並且,在你進行比較的時候,你的程式會更複雜。
當然,這裡並不是說你就不能使用null了,現實情況是很複雜的,依然會有些情況下,你需要使用null值。
2.固定長度的表會更快
如果表中的所有欄位都是「固定長度」的,整個表會被認為是 「static」 或 「fixed-length」。 例如,表中沒有如下型別的字段: varchar,text,blob。只要你包括了其中乙個這些字段,那麼這個表就不是「固定長度靜態表」了,這樣,mysql 引擎會用另一種方法來處理。
固定長度的表會提高效能,因為mysql搜尋得會更快一些,因為這些固定的長度是很容易計算下乙個資料的偏移量的,所以讀取的自然也會很快。而如果字段不是定長的,那麼,每一次要找下一條的話,需要程式找到主鍵。
並且,固定長度的表也更容易被快取和重建。不過,唯一的***是,固定長度的字段會浪費一些空間,因為定長的字段無論你用不用,他都是要分配那麼多的空間。
3.垂直分割
"垂直分割"是一種把資料庫中的表按列變成幾張表的方法,這樣可以降低表的複雜度和字段的數目,從而達到優化的目的。
示例一:在users表中有乙個欄位是家庭位址,這個欄位是可選字段,相比起,而且你在資料庫操作的時候除了個人資訊外,你並不需要經常讀取或是改寫這個字段。那麼,為什麼不把他放到另外一張表中呢? 這樣會讓你的表有更好的效能,大家想想是不是,大量的時候,我對於使用者表來說,只有使用者id,使用者名稱,口令,使用者角色等會被經常使用。小一點的表總是會有好的效能。
示例二: 你有乙個叫 「last_login」 的字段,它會在每次使用者登入時被更新。但是,每次更新時會導致該錶的查詢快取被清空。所以,你可以把這個字段放到另乙個表中,這樣就不會影響你對使用者id,使用者名稱,使用者角色的不停地讀取了,因為查詢快取會幫你增加很多效能。
另外,你需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去join他們,不然的話,這樣的效能會比不分割時還要差,而且,會是極數級的下降。
4.越小的列會越快
對於大多數的資料庫引擎來說,硬碟操作可能是最重大的瓶頸。所以,把你的資料變得緊湊會對這種情況非常有幫助,因為這減少了對硬碟的訪問。
參看 mysql 的文件 storage requirements 檢視所有的資料型別。
如果乙個表只會有幾列罷了(比如說字典表,配置表),那麼,我們就沒有理由使用 int 來做主鍵,使用 mediumint, smallint 或是更小的 tinyint 會更經濟一些。如果你不需要記錄時間,使用 date 要比 datetime 好得多。
當然,你也需要留夠足夠的擴充套件空間,不然,你日後來幹這個事,你會死的很難看,參看slashdot的例子(2023年11月06日),乙個簡單的alter table語句花了3個多小時,因為裡面有一千六百萬條資料。
mysql優化整理01
mysql資料庫的優化技術 對mysql的優化是乙個綜合型的技術,主要包括 a.表的設計合理化 符合3nf b.新增適當索引 普通索引,逐漸索引,唯一索引,全文索引 c.分表技術 水平分割,垂直分離 d.讀寫分離 e.儲存過程 模組化程式設計,可以提高速度 但移植性不好 f.對mysql配置優化 m...
mysql優化點整理
優化sql一般步驟 1.通過show session 或者 global status來檢視 當前連線 或者 資料庫上次開機以來 的伺服器狀態資訊,預設是session 例如 show status like com com 表示 語句執行的總次數,這總次數是針對所有引擎的總和 show statu...
mysql優化整理 索引
索引是表記錄的單個或多個字段重新組織的一種方法,其目的是提高資料庫的查詢速度,本質上就是一種資料結構。索引的型別 primary 主鍵 secondary 其他 檢視是否使用索引方式 可以使用 explain sql語句,檢視所查詢的語句是否使用了建立的索引,進而優化自己的索引建立。主要字段說明 s...