一、優化介紹
數據結構、SQL、索引是成本最低,且效果最好的優化手段。
二、優化方向
1. SQL 以及索引的優化
首先要根據需求寫出結構良好的 SQL,然後根據 SQL 在表中建立有效的索引。但是如果索引太多,不但會影響寫入的效率,對查詢也有一定的影響。
2. 合理的數據庫設計
(1)根據數據庫三範式來進行表結構的設計。設計表結構時,就需要考慮如何設計才能更有效的查詢。
數據庫三範式:
- 第一範式:數據表中每個字段都必須是不可拆分的最小單元,也就是確保每一列的原子性;
- 第二範式:滿足一範式後,表中每一列必須有唯一性,都必須依賴於主鍵;
- 第三範式:滿足二範式後,表中的每一列只與主鍵直接相關而不是間接相關 (外鍵也是直接相關),字段沒有冗餘。
(2)有時候可以根據場景合理地反規範化:
- 分割表。
- 保留冗餘字段。當兩個或多個表在查詢中經常需要連接時,可以在其中一個表上增加若干冗餘的字段,以 避免表之間的連接過於頻繁,一般在冗餘列的數據不經常變動的情況下使用。
- 增加派生列。派生列是由表中的其它多個列的計算所得,增加派生列可以減少統計運算,在數據彙總時可以大大縮短運算時間。
(3)數據庫五大約束:
- PRIMARY key: 設置主鍵約束;
- UNIQUE:設置唯一性約束,不能有重複值;
- DEFAULT 默認值約束
- NOT NULL:設置非空約束,該字段不能爲空;
- FOREIGN key : 設置外鍵約束。
(4)字段類型選擇:
- 儘量使用 TINYINT、SMALLINT、MEDIUM_INT 作爲整數類型而非 INT,如果非負則加上 UNSIGNED
- VARCHAR 的長度只分配真正需要的空間
- 使用枚舉或整數代替字符串類型
- 儘量使用 TIMESTAMP 而非 DATETIME
- 單表不要有太多字段,建議在 20 以內
- 避免使用 NULL 字段,很難查詢優化且佔用額外索引空間
3.優化的步驟
(1)代碼優化
第一步就應該是分析相關的代碼,找出相應的瓶頸,再來考慮具體的優化策略。有一些性能問題,完全是由於代碼寫的不合理,通過直接修改一下代碼就能解決問題的,比如 for 循環次數過多、作了很多無謂的條件判斷、相同邏輯重複多次等。
(2)定位慢 SQL,並優化
由自帶的慢查詢日誌或者開源的慢查詢系統定位到具體的出問題的 SQL,然後使用 explain、profile 等工具來逐步調優,最後經過測試達到效果後上線。
-
slow_query_log 慢查詢開啓狀態。
-
slow_query_log_file 慢查詢日誌存放的位置(這個目錄需要 MySQL 的運行帳號的可寫權限,一般設置爲 MySQL 的數據存放目錄)。
-
long_query_time 查詢超過多少秒才記錄。
當在配置文件中開啓慢查詢日誌記錄之後,就會在指定的存放目錄生成日誌文件。
三、優化方案
(一)語句優化
- 連續數值條件,用 BETWEEN 不用 IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
- Update 語句,如果只更改 1、2 個字段,不要 Update 全部字段,否則頻繁調用會引起明顯的性能消耗
- 儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型
- 不建議使用 select * from t ,用具體的字段列表代替 “*”,不要返回用不到的任何字段。儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理
- 表與表之間通過一個冗餘字段來關聯,要比直接使用 JOIN 有更好的性能
- select count (*) from table;這樣不帶任何條件的 count 會引起全表掃描
- 在搜索字符型字段時,我們有時會使用 LIKE 關鍵字和通配符,這種做法雖然簡單,但卻也是以犧牲系統性能爲代價的。
(二)合理使用索引
索引一般情況下都是高效的。但是由於索引是以空間換時間的一種策略,索引本身在提高查詢效率的同時會影響插入、更新、刪除的效率,頻繁寫的表不宜建索引。
1.索引類型
- 主鍵索引 (PRIMARY KEY)
- 唯一索引 (UNIQUE)
- 普通索引 (INDEX)
- 組合索引 (INDEX)
- 全文索引 (FULLTEXT)
2.注意
- 在建有索引的字段上儘量不要使用函數進行操作。
- 儘量不要在 where 子句中對字段進行 null 值判斷或者使用!= 或 <> 操作符,否則將導致引擎放棄使用索引而進行全表掃描
(三)分表
1.分表方式
水平分割(按行)、垂直分割 (按列)
2.分表場景
- 根據經驗,mysql 表數據一般達到百萬級別,查詢效率就會很低。
- 一張表的某些字段值比較大並且很少使用。可以將這些字段隔離成單獨一張表,通過外鍵關聯,例如考試成績,我們通常關注分數,不關注考試詳情。
3.水平分表策略
- 按時間分表:當數據有很強的實效性,例如微博的數據,可以按月分割。
- 按區間分表:例如用戶表 1 到一百萬用一張表,一百萬到兩百萬用一張表。
- hash 分表:通過一個原始目標 id 或者是名稱按照一定的 hash 算法計算出數據存儲的表名。
【Java 面試那點事】
這裏致力於分享 Java 面試路上的各種知識,無論是技術還是經驗,你需要的這裏都有!
這裏可以讓你【快速瞭解 Java 相關知識】,並且【短時間在面試方面有跨越式提升】
面試路上,你不孤單!