首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

PreparedStatement vs Statement:性能、安全性與批量操作實測

     編輯:C++ 入門

核心差異總覽

維度StatementPreparedStatement
SQL 編譯每次執行都編譯預編譯一次,多次復用
計劃緩存不緩存DB 自動緩存執行計劃
參數傳遞字符串拼接佔位符 ? 綁定
SQL 注入防護無自動轉義,有效防禦
代碼可讀性拼接字符串難維護結構清晰,參數分離

性能實測:插入 10 萬條數據

// 環境:Oracle + JDBC,批量提交閾值 250
@Test
void testPreparedStatementBatch() {  // 470 ms
    String sql = "insert into dept values(?,?)";
    PreparedStatement ps = conn.prepareStatement(sql);
    for (int i = 0; i < 100000; ++i) {
        ps.setInt(1, i+1);
        ps.setString(2, "dept_" + (i+1));
        ps.addBatch();
        if ((i+1) % 250 == 0) { ps.executeBatch(); ps.clearBatch(); }
    }
}

@Test
void testStatementBatch() {          // 98,000 ms
    Statement st = conn.createStatement();
    for (int i = 0; i < 100000; ++i) {
        String sql = "insert into dept values(" + (i+1) + ",'dept_" + (i+1) + "')";
        st.addBatch(sql);
        if ((i+1) % 250 == 0) { st.executeBatch(); st.clearBatch(); }
    }
}

結論:PreparedStatement 批量插入比 Statement 快 200 倍以上,主要得益於預編譯計劃復用與網絡交互減少。

防 SQL 注入原理

// Statement 風險示例
String sql = "SELECT * FROM user WHERE name = '" + userInput + "'";
// 輸入 ' OR '1'='1 導致永真條件

// PreparedStatement 安全
String sql = "SELECT * FROM user WHERE name = ?";
ps.setString(1, userInput);  // 參數作為數據傳遞,不參與 SQL 解析

最佳實踐清單

  1. 默認使用 PreparedStatement,除非極簡單的一次性 DDL
  2. 批量操作必須用 addBatch/executeBatch,並設置合適提交閾值(經驗值 500~1000)
  3. 關閉資源順序:ResultSet → Statement → Connection(或用 try-with-resources)
  4. 避免在循環中創建 PreparedStatement,移到循環外複用
  5. 大字段(BLOB/CLOB)用 setBinaryStream/setCharacterStream 流式寫入

原始碼片段

完整 JUnit 測試代碼見原文,涵蓋四種場景對比:

  • Statement 單條執行:98 秒
  • PreparedStatement 單條:47 秒
  • Statement + 批量:98 秒(無提升,因 SQL 文本仍不同)
  • PreparedStatement + 批量:0.47 秒(最優)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved