# 使用预编译语句 API

__*useServerPrepStmts*__

+ `OLTP` 友好
+ `useServerPrepStmts`

```12
jdbc:mysql://<tidb_server>:<port>/<db_name>?~!@useServerPrepStmts=true@!~
```

---------------------------------------------------------------------------
对于 OLTP 场景,程序发送给数据库的 SQL 语句在去除参数变化后都是可穷举的某几类,因此建议使用预处理语句 (Prepared Statements) 代替普通的文本执行,并复用预处理语句来直接执行,从而避免 TiDB 重复解析和生成 SQL 执行计划的开销。

1. 性能提升
形如 select * from user where id = 1,这种普通语句叫做 Immediate Statement,执行时要经历完整的SQL执行过程
形如select * from user where id = ?, 使用占位符代替语句中字段的值,这种语句叫做Prepared Statement,执行时,首先要进行预编译,之后每次执行都省去了解析优化等过程。
预编译语句适用场景:一条SQL语句需要反复执行多次并且只有字段的值可能存在改变（如query的where子句值不同,update的set子句值不同,insert的values值不同）

2. 安全性
在jdbc中使用PreparedStatement是必要的,可以有效地防止sql注入。

目前多数上层框架都会调用 Prepare API 进行 SQL 执行,如果直接使用 JDBC API 进行开发,注意选择使用 Prepare API。
另外需要注意 MySQL Connector/J 实现中默认只会做客户端的语句预处理,会将 ? 在客户端替换后以文本形式发送到服务端,所以除了要使用 Prepare API,还需要在 JDBC 连接参数中配置 useServerPrepStmts = true,才能在 TiDB 服务器端进行语句预处理。