原始代碼(3-4 秒)
String sql = "SELECT cid FROM b"; // 全表掃描 45 萬行
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
if (rs.getInt("cid") == targetId) return false;
}
優化後(毫秒級)
String sql = "SELECT COUNT(*) FROM b WHERE cid = ?"; // 命中主鍵索引
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, targetId);
try (ResultSet rs = ps.executeQuery()) {
return rs.next() && rs.getInt(1) == 0;
}
}
優化點對比
| 指標 | 原始 | 優化後 |
| 網絡傳輸 | 45 萬行 × 列數 | 1 行 1 列 |
| JVM 對象創建 | 45 萬 ResultSet 行對象 | 1 個 |
| 數據庫執行計劃 | Full Table Scan | Index Unique Scan |
| 耗時 | 3-4 秒 | < 5 ms |
必要條件
- cid 必須有索引:主鍵自動建立唯一索引,若非主鍵需手動
CREATE INDEX idx_cid ON b(cid)
- 使用 PreparedStatement:預編譯複用執行計劃,防注入
- 連接池:HikariCP/Druid 避免頻繁建連開銷
擴展:批量檢查
// 一次檢查多個 ID
String sql = "SELECT cid FROM b WHERE cid IN (?,?,?,?)"; // 最多 1000 參數
// 或臨時表
CREATE TEMPORARY TABLE tmp_ids (cid INT PRIMARY KEY);
INSERT INTO tmp_ids VALUES (...);
SELECT t.cid FROM tmp_ids t LEFT JOIN b ON t.cid = b.cid WHERE b.cid IS NULL;