{%hackmd DfWYF9cYREebVNN1eEOz-w %} # 性能優化 ###### tags: `性能優化` `202205` [](https://zhuanlan.zhihu.com/p/493952557) 性能調教 - [優化 sql](https://hackmd.io/@GoldxTree/SkXgukR9K) - 使用 join 要注意 - 多用 top - 避免使用 * - 少用子查詢 - 確認是否有沒用到索引的: where 的欄位, order by 的欄位 - 確認索引是否有生效, 看執行計畫. - 索引在某些特殊情況下會失效, db engine 不去走 - 使用 select *, 對索引做邏輯運算, - like 運算式開頭為 % - or, is null, is not null ... - 若情境需需要呼叫多個 API, 使用多執行緒去分別完成可降低等待所消耗的時間 - 若有資料存放於多個 table, 且各 table 都有很大的資料量. 可將資料同步到 redis, 但須注意資料一致性的問題. - 程式端使用迴圈的地方, 如果有操作(DB, API, File IO)的要小心. 注意是否有多次進行呼叫的邏輯. - 程式端注意是否有無用的判斷邏輯,或過於複雜的邏輯。並降低重複的程式碼。 - 若可用非同步設計的需求, 盡量使用非同步. 比如寄信, 儲存使用者操作紀錄. 可改由 mq 來協助, 加速流程. - 鎖的粒度: table? 整筆資料? 欄位? - 程式上鎖的粒度: - 粒度越小越好 - 如果有多台主機可考慮, redis 分布式的鎖. [](https://developer.aliyun.com/article/854283) - catch (需注意資料即時性, 與資料不一致等議題) - catch server - redis - 於 AP 上管理 catch - SQL 的依據特定功能分庫分表, 比如將用戶數切成三個 DB 存放, 每個 DB 中又有不同 Table 來存放. :::info - [](https://cloud.tencent.com/developer/article/1901963) - 這裡的分表指的是資料存放到哪個 DB、table,不是拆分表格欄位(正規化)的那種。 - 水平方向: 主從架構,將讀寫去做分離。通常系統查詢的次數會遠高於異動資料,可以用 82 法則來形容。所以系統為了使用者體驗,優化讀取是首要考量。 - 垂直方向 - DB: 因業務增加使資料量越來越大,使得 query 成本越來越高,此時單個 DB 因應不同功能的 query 會越來越慢。所以會依照功能去化分 DB,將成本分散在各個 DB **達到整體性能的提升**。(比如財務資料依年度存放於不同 DB) - 垂直方向 - table: 同樣是因為資料量大,將相同類型的資料存放在不同的 table。(比如財務資料一年度存放於不同 table) - 總結 - 水平方向的: 是針對讀寫的邏輯做拆分。主從的資料結構會是完全相同的。以操作 DB 的邏輯來看相對上較簡單。 - 垂直方向的: 針對的是業務功能去拆分。是將巨量的資料分散於不同的地方的一種策略。以操作 DB 的邏輯來看較複雜。(警慎考慮,可用 NoSql 來替代) ::: - 垂直 - 分 DB 情境: 依據用戶的區域做區別,存放到不同的 DB - 分 Table 情境: 依據用戶的 ID 區段去存放到不同的 Table(e.g 1~1000000 存放到 Table01) - 最好謹慎考量使用場景,來決定要拆到 DB 或 table。因將會大幅提升程式複雜度。(需考量: 複雜度、成本、DB 成本攤提、預期資料量、開發複雜度、維運複雜度) - 系統要監控什麼? 是否要收集後做成 Dashboard?? - CPU 使用率 - 記憶體 使用率 - 磁碟 IO 使用率 - 磁碟使用空間 - SQL 使用情形 - SQL 的慢查詢 - API 響應時間