预编译SQL的缺陷

本文探讨了使用JDBC PrepareStatement接口进行预编译SQL的执行效率,指出其在数据分布不均的情况下可能产生的性能瓶颈。通过分析执行计划的固定性与数据分布之间的关系,解释了为何在某些情况下全表扫描反而更高效。

    众所周知,JDBC的PrepareStatement接口可以进行预编译SQL。这样数据库会将编译后的SQL绑定在这个连接上,只需要不断的进行参数替换就可以提高SQL的执行效率。但是这样的设计是有缺陷的,并不是所有的情况都会提高执行效率,反而也会有最差的情况。

废话不多说。因为数据库的预编译一但创建,执行计划就会一成不变的被保存起来(预编译SQL)。因此,他不可能去适应所有的情况。比如说下面的SQL:

SELECT * FROM USER WHERE LOCATION = '广西'

    假如说,USER表中存储的数据中,“地域”这个字段分配的很广,也就是说他的取值区间平均来说很广。数据库会认为,索引的选择性较好。(PS:何为选择性?假如说性别,一万条数据里只有两种可能,那么他的选择性就不好。因为,索引的B+树只会存在两个结点,数据太过于聚集)所以,这条执行计划就会利用索引。假如说,来自“广西”的USER很少,那么确实取出速度会很快。假如说这条SQL:

SELECT * FROM USER WHERE LOCATION = '上海'

    因为在上海的USER特别多,假如说有上千条记录,那么返回的数据特别多,就回产生很多随机读取。因为,LOCATION不是主键,数据库是按照主键进行聚簇的。这时候,用索引就会相当慢。为什么?

    因为在MYSQL中,如果走索引,就会访问两次硬盘。因为,索引的B+树中存储的DATA并不是表数据的集邮物理位置(RowID),而是主键!他会拿着主键再去磁盘上寻找真实的数据。为什么要这样?因为假如索引有10000个,那么更改主键的话,那么这些数据就不得不搬到合适的物理位置。这样,就会更改10000处!但是并不是所有的数据库都是这么做的,比如ORACLE。ORACLE索引中的数据不仅有主键还有集邮物理位置(RowID),这样做的想法是,住建部可能经常更换。他先拿物理位置(RowID)去取出真实数据,然后和主键比较一下,如果不对再拿主键去取,然后更新中的物理位置(RowID)。这样做的话,就会出现最好情况和最差情况了。

    所以数据量不大的时候,还不如全表扫描来得快。

### 解决 Intellij IDEA 连接数据库预编译报错 当在IntelliJ IDEA中尝试连接数据库并执行SQL语句时,可能会遇到各种类型的预编译错误。这些错误的原因多种多样,可能是由于网络配置不当、驱动程序缺失或是代码中的语法问题引起的。 #### 网络配置检查 如果IDEA无法成功建立到目标数据库的连接,则应首先确认本地机器能够正常访问远程服务器。例如,在Linux环境中,防火墙设置可能导致连接失败。此时可以考虑暂时停止防火墙服务来测试连通性: ```bash systemctl stop firewalld.service ``` 这一步骤有助于排除因网络安全策略而导致的问题[^4]。 #### JDBC驱动验证 确保项目已正确引入所需的JDBC驱动库,并且版本兼容所使用的数据库管理系统(DBMS)。可以通过Maven或Gradle管理依赖项,也可以手动下载相应的jar包并将其添加至项目的classpath下。 对于MySQL而言,典型的pom.xml片段如下所示: ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> ``` #### SQL脚本审查 仔细检查用于创建表结构或其他DDL/DML命令的SQL文件是否存在潜在缺陷。某些情况下,“找不到符号”的Java编译器警告也可能源于嵌入式SQL查询内的拼写失误或者未声明的对象名称[^2]。 #### 同步数据库元数据 每当更改了数据库模式定义之后(比如新增字段),应当立即刷新IDE内部缓存以便获取最新的架构信息。具体来说就是点击工具栏上的“同步当前的数据库连接”按钮(图标1),从而保证后续操作基于最新状态展开工作[^3]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值