首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

PHP 與 MySQL 效能優化實戰清單:從 SQL、索引、架構到快取的系統化指南

     編輯:MySQL 資料庫相關知識

前言

PHP + MySQL 是 Web 開發的經典組合,但隨著流量增長,資料庫往往成為系統瓶頸。本文將優化手段分為 MySQL 層 (SQL、索引、架構、引擎) 與 PHP 層 (快取、編譯、輸出) 兩大維度,提供 30+ 具體可執行的優化項目,並標註優先級與適用場景,作為效能調校的系統化清單。

第一部分:MySQL 效能優化

■ 核心觀測與診斷 (優先級:P0 - 必做)

項目工具/指令關鍵指標行動閾值
慢查詢日誌long_query_time=1, log_queries_not_using_indexes=ON查詢時間、掃描行數、未用索引> 1s 或未命中索引即記錄
執行計劃分析EXPLAIN / EXPLAIN ANALYZE (8.0.18+)type、key、rows、Extra (Using filesort/temporary)非 const/ref/range、出現 filesort/temporary
狀態變數監控SHOW GLOBAL STATUSHandler_read_rnd_next (全掃)、Created_tmp_disk_tables、Slow_queries持續增長或佔比高
InnoDB 監控SHOW ENGINE INNODB STATUSBuffer Pool 命中率、鎖等待、死鎖、歷史清理命中率 < 99%、鎖等待 > 10ms

■ SQL 與索引優化 (優先級:P0 - 高收益)

  1. 避免 SELECT *:明確列出欄位,減少網路傳輸、覆蓋索引命中機率、避免未來 Schema 變更衝擊。
  2. WHERE 條件用索引欄位:EXPLAIN 確認 type=ref/range、key 非 NULL。
  3. 複合索引遵循最左前綴:等值條件在前、範圍條件在後、排序欄位最後。
    範例:WHERE a=1 AND b>2 ORDER BY c → 索引 (a, b, c) 或 (a, c) (視基數而定)。
  4. 避免隱式轉型導致索引失效:WHERE varchar_col = 123 → 全表掃描。修正:WHERE varchar_col = '123'。
  5. LIKE 模糊查詢優化:LIKE 'abc%' 可用索引;LIKE '%abc' / LIKE '%abc%' 無法用索引 → 改用全文索引或 Elasticsearch。
  6. OR 條件優化:WHERE a=1 OR b=2 通常走全表掃描 → 改用 UNION ALL 分開查詢合併。
  7. 分頁優化 (深分頁問題):LIMIT 100000, 20 掃描 10 萬行 → 改用 延遲關聯 或 游標分頁 (WHERE id > last_id LIMIT 20)。
  8. 覆蓋索引:查詢欄位全部包含於索引中 (Using index),避免回表。
    範例:SELECT id, name FROM users WHERE status=1 → 索引 (status, id, name)。
  9. 定期 OPTIMIZE / ANALYZE:見 維護語句指南。
  10. 避免在索引欄上使用函數/運算:WHERE DATE(created_at) = '2024-01-01' → WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02'。

■ 架構與引擎選擇 (優先級:P1 - 架構層面)

場景推薦引擎關鍵配置
核心交易、強一致性、行級鎖、事務InnoDB (預設)innodb_buffer_pool_size = 物理記憶體 70-80%、innodb_flush_log_at_trx_commit=1、innodb_file_per_table=ON
唯讀/極少寫入、全文搜尋、空間索引MyISAMkey_buffer_size、myisam_sort_buffer_size
暫存資料、極高速讀寫、可接受重啟丟失MEMORYmax_heap_table_size、tmp_table_size
日誌、歸檔、壓縮、僅追加寫入Archive無特殊調校
InnoDB 關鍵參數速查 (8.0, 32GB 記憶體範例)
[mysqld]
innodb_buffer_pool_size = 24G
innodb_buffer_pool_instances = 16
innodb_log_file_size = 4G
innodb_log_files_in_group = 2
innodb_log_buffer_size = 256M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_page_cleaners = 4
innodb_max_dirty_pages_pct = 90
innodb_max_dirty_pages_pct_lwm = 10

■ 分庫分表與讀寫分離 (優先級:P2 - 流量爆發時)

  • 垂直拆分:業務模組解耦,不同庫部署不同實例 (用戶庫、訂單庫、日誌庫)。
  • 水平分表:單表 > 2000 萬行或 > 20GB 時考慮。分片鍵選擇:用戶 ID、商家 ID、時間範圍。中間層推薦 ShardingSphere、MyCat、Vitess。
  • 讀寫分離:一主多從,Proxy 層 (ProxySQL、MaxScale) 自動路由 SELECT 至從庫。注意:從庫延遲導致讀舊資料,關鍵業務強制走主庫。

■ 查詢快取與緩衝區 (優先級:P1 - 8.0 已移除 Query Cache)

  • MySQL 5.7:query_cache_type=DEMAND、query_cache_size=256M,搭配 SQL_CACHE/SQL_NO_CACHE 精準控制。
  • MySQL 8.0:Query Cache 已移除,改用應用層快取或 ProxySQL Query Cache。
  • InnoDB Buffer Pool 才是核心快取,務必配置足夠大小並監控命中率。

第二部分:欄位與資料型態優化 (優先級:P1 - 設計階段決定)

  1. 用最小足夠的型態:TINYINT 代替 INT 存狀態、MEDIUMINT 代替 INT 存中等 ID (省 25%)。
  2. 優先 NOT NULL:每欄省 1 bit,優化器統計更準,避免 IS NULL 判斷開銷。
  3. 定長優於變長 (特定場景):無 VARCHAR/TEXT/BLOB 時,ROW_FORMAT=FIXED 加速定位;但會浪費空間,權衡後決定。
  4. 非多語系欄位用 latin1/ascii:Email、URL、IP、MD5、UUID 等純 ASCII 欄位,CHARSET=latin1 節省 50-75% 空間 (vs utf8mb4)。
  5. IP 存無號整數:INET_ATON()/INET_NTOA(),INT UNSIGNED 4 位元組 vs VARCHAR(45) 45 位元組,支援範圍查詢 (BETWEEN)。
  6. 金額用 DECIMAL(19,4) 或 BIGINT 分為單位:嚴禁 FLOAT/DOUBLE 存金額。
  7. Enum/Set 慎用:修改枚舉值需 DDL 鎖表,新增值需 ALTER TABLE;建議用 TINYINT + 應用層字典映射。

第三部分:PHP 層效能優化

■ 快取策略 (優先級:P0 - 立竿見影)

層級技術適用資料TTL 建議關鍵指標
Opcode 快取OPcache (PHP 內建)編譯後位元組碼永久 (部署時清除)命中率 > 99%
資料物件快取Redis / Memcached熱點查詢結果、Session、Token、計數器秒~天 (業務決策)命中率 > 95%、P99 < 5ms
HTTP 快取Varnish / Nginx fastcgi_cache / CDN靜態/半靜態頁面、API 回應分鐘~小時命中率 > 90%
本地快取APCu / PHP 陣列靜態變數極熱配置、字典表、單機去重請求生命週期~分鐘無網路延遲
OPcache 生產推薦配置
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=20000
opcache.revalidate_freq=0  ; 生產 0 需部署時重啟 PHP-FPM
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.fast_shutdown=1

■ 輸出與傳輸優化

  • 啟用 Gzip/ Brotli 壓縮:Nginx gzip on; gzip_types text/css application/json application/javascript; 或 brotli on;。
  • 靜態資源 CDN + 長期快取:Cache-Control: public, max-age=31536000, immutable,檔名帶 Hash 版本號。
  • 頁面靜態化:商品詳情、文章頁、列表首頁定時生成靜態 HTML,Nginx 直接服務,繞過 PHP-FPM。
  • 減少 HTTP 請求:CSS/JS 合併、Sprite 圖、內聯關鍵 CSS。

■ 程式碼層面優化

  1. 避免 N+1 查詢:批次載入關聯資料 (WHERE id IN (...)) 或 Eager Loading (Laravel with(), Doctrine join)。
  2. 資料庫連線池:Swoole/RoadRunner 長連線模式,或 PHP-FPM mysqli::persistent / PDO ATTR_PERSISTENT (需配合 wait_timeout 調整)。
  3. 大量寫入用批次 INSERT:INSERT INTO t (a,b) VALUES (1,2),(3,4)... 單次 1000-5000 行,配合 LOAD DATA INFILE 更快。
  4. 異步處理耗時任務:發送郵件、推播、報表生成 → 推入 Queue (Redis/RabbitMQ) → Worker 消費。

第四部分:優化執行清單 (Checklist)

階段動作項目驗收標準負責角色
上線前所有核心 SQL EXPLAIN 驗收無 ALL、無 filesort、無 temporary、索引命中DBA + RD
上線前慢查詢閾值設為 1s 並跑壓測慢查詢數 = 0DBA
上線後 Day 1啟用慢查詢日誌、監控儀表板Grafana 儀表板上線DBA
每週檢視 Top 10 慢查詢、索引使用率優化或標記風險DBA
每月大表碎片評估、OPTIMIZE 排程Data_free < 20%DBA
每季全量備份恢復演練、參數複盤RTO < 30min、RPO = 0DBA + Ops

結語

效能優化是系統工程,而非單點技巧。建立 觀測 → 診斷 → 優化 → 驗證 → 固化 的閉環流程,將優化項目納入開發規範與上線清單,才能從根本上解決 PHP + MySQL 架構的擴展性挑戰。本文清單可作為團隊內部優化標準的基準版本,請根據業務實況裁剪調整。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved