---
# System prepended metadata

title: 性能優化
tags: [性能優化, '202205']

---

{%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 響應時間