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

MySQL 隨機查詢優化實戰:從 8 秒降到 0.01 秒的完整調優過程

     編輯:MySQL 資料庫相關知識

問題現場

15 萬筆資料表,`SELECT * FROM t ORDER BY RAND() LIMIT 5` 耗時 8 秒+。官方文檔明確警告:`RAND()` 在 `ORDER BY` 中會被多次評估,導致效能崩潰。

演進過程對比

版本SQL 寫法耗時缺點
v1ORDER BY RAND() LIMIT 58 秒全表掃描+檔案排序
v2JOIN (SELECT ROUND(RAND()*MAX(id)) AS id) ...0.01 秒產生連續 5 筆(非真隨機)
v3WHERE id >= (SELECT FLOOR(MAX(id)*RAND())) ... LIMIT 10.5 秒子查詢執行多次
v4WHERE id >= (SELECT FLOOR(RAND()*(MAX-MIN)+MIN)) ... LIMIT 10.01 秒單次隨機,但需執行 5 次取 5 筆
v5 (最佳)JOIN (SELECT ROUND(RAND()*(MAX-MIN)+MIN) AS id) ... LIMIT 10.0015 秒JOIN 寫法優於 WHERE 子查詢

最終最佳 SQL(取 1 筆,PHP 循環 5 次)

SELECT * FROM `table` AS t1
JOIN (
  SELECT ROUND(
    RAND() * (
      (SELECT MAX(id) FROM `table`) - (SELECT MIN(id) FROM `table`)
    ) + (SELECT MIN(id) FROM `table`)
  ) AS id
) AS t2 ON t1.id >= t2.id
ORDER BY t1.id LIMIT 1;

關鍵優化點

  1. 避免 ORDER BY RAND():不產生臨時表與檔案排序。
  2. 利用主鍵範圍隨機:`MIN(id)` ~ `MAX(id)` 之間隨機取點,再 `>=` 向後取第一筆(主鍵索引極快)。
  3. JOIN 替代 WHERE 子查詢:MySQL 對 JOIN 優化較好,執行計劃更穩定。
  4. 處理 ID 不連續:`>=` 配合 `ORDER BY id LIMIT 1` 保證能取到存在的行。

PHP 批次取 5 筆不重複範例

$ids = [];
for ($i=0; $i<5; $i++) {
    $sql = "上面的最佳SQL";
    $row = $pdo->query($sql)->fetch();
    if ($row && !in_array($row['id'], $ids)) {
        $ids[] = $row['id'];
        $results[] = $row;
    }
}

總耗時約 0.007 秒,較原 8 秒提升 1000 倍。

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