Jdbc execute 比工具速度慢
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jdbc execute 比工具速度慢相关的知识,希望对你有一定的参考价值。
参考技术A Jdbc执行慢,PLSQL执行快。Jdbc执行慢主要是代码问题,jdbc执行sql慢时,在执行sql的preparedStatement中有个设置编码的方法:preparedStatement.setBytes,把占位符的数据用getBytes(Charset)转换编码后设进去即可。
为啥带有'exists'的sql运行速度比使用MySQL的'in'慢
【中文标题】为啥带有\'exists\'的sql运行速度比使用MySQL的\'in\'慢【英文标题】:why sql with 'exists' run slower than 'in' using MySQL为什么带有'exists'的sql运行速度比使用MySQL的'in'慢 【发布时间】:2013-12-08 23:08:12 【问题描述】:我是 MySQL 优化的新手,我发现了一个惊人的事情:带有 'exists' 的 sql 运行速度比使用 'in' 慢!!!
以下是我的 DDL:
mysql> `show create table order\G`;
*************************** 1. row ***************************
Table: order
Create Table: CREATE TABLE `order` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`employee_id` int(4) NOT NULL,
`price` decimal(7,2) NOT NULL,
`trade_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_employee_id` (`employee_id`),
CONSTRAINT `fk_employee_id` FOREIGN KEY (`employee_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=231001 DEFAULT CHARSET=utf8
mysql> `show create table order_detail\G`;
*************************** 1. row ***************************
Table: order_detail
Create Table: CREATE TABLE `order_detail` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`menu_id` int(4) NOT NULL,
`order_id` int(4) NOT NULL,
`amount` int(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_menu_id` (`menu_id`),
KEY `fk_order_id` (`order_id`),
CONSTRAINT `fk_menu_id` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`),
CONSTRAINT `fk_order_id` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1037992 DEFAULT CHARSET=utf8
Query Solution 1: use exists
---------------------------------
mysql> `SELECT count(`order`.id) FROM `order` WHERE EXISTS ( SELECT 1 FROM order_detail WHERE order_detail.order_id = `order`.id GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 );`
+-------------------+
| count(`order`.id) |
+-------------------+
| 92054 |
+-------------------+
1 row in set (***6.53 sec***)
mysql> `explain SELECT count(`order`.id) FROM `order` WHERE EXISTS ( SELECT 1 FROM order_detail WHERE order_detail.order_id = `order`.id GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 )\G;`
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: order
type: index
possible_keys: NULL
key: fk_employee_id
key_len: 4
ref: NULL
rows: 231032
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: order_detail
type: ref
possible_keys: fk_order_id
key: fk_order_id
key_len: 4
ref: performance_test.order.id
rows: 3
Extra: Using where; Using index
2 rows in set (0.01 sec)
Query solution 2: use in
------------------------
mysql> `SELECT count(`order`.id) FROM `order` WHERE `order`.id IN ( SELECT order_detail.order_id FROM order_detail GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 ) ;`
+-------------------+
| count(`order`.id) |
+-------------------+
| 92054 |
+-------------------+
1 row in set (***3.88 sec***)
mysql> `explain SELECT count(`order`.id) FROM `order` WHERE `order`.id IN ( SELECT order_detail.order_id FROM order_detail GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 ) \G;`<br>
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: order
type: index
possible_keys: NULL
key: fk_employee_id
key_len: 4
ref: NULL
rows: 231032
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: SUBQUERY
table: order_detail
type: index
possible_keys: fk_order_id
key: fk_order_id
key_len: 4
ref: NULL
rows: 1036314
Extra: Using index
2 rows in set (0.00 sec)
【问题讨论】:
这是一个测试项目,如果你想重现这种情况,我可以导出测试数据并分享它 我认为问题出在依赖子查询上 您是否尝试过颠倒执行顺序:在 IN 之前和 EXIST 之后,可能是第二个查询使用的缓存执行计划(来自第一个查询)。 我认为 EXISTS 查询在外部查询上执行 JOIN,因此从数据库中读取的数据更多 (sqlmag.com/database-performance-tuning/advanced-join-techniques)。在使用索引过滤外部查询之后,IN 查询首先执行子查询(读取所有记录)。 我相信你需要阅读其他类似的帖子,这里有一个***.com/questions/3999600/…它很详细 【参考方案1】:我认为你有点困惑,你有一个错误的想法,'EXISTS' 比'IN' 工作得更快,我试图让你理解原因..
EXISTS 返回一个布尔值,并将在第一次匹配时返回一个布尔值。因此,如果您正在处理重复/倍数,“EXISTS”将比“IN”或“JOIN”更快地执行,具体取决于数据和需求。
而“IN”是 OR 子句的语法糖。虽然它非常适合,但在处理该比较的大量值时存在问题(1,000 以北)。在重复/倍数的情况下,“IN”检查所有存在的值,这自然会比“EXISTS”消耗更多的执行时间,这就是为什么“IN”总是比“EXISTS”慢。
我希望我能澄清你的困惑。
【讨论】:
感谢您的回复,我在网上搜索了更多资料,也许本质区别不是“存在”和“输入”,而是“分组依据”对子查询的影响,因为我有使用'Group By'子句,所以'Exists'的快捷方式不存在,这两个查询都必须全扫描表或索引。我喜欢这两个查询的解释输出有点不同,Select_Type的'Exists' 中的 SubQuery 是 'Dependent Subquery',但另一个是 'SubQuery'【参考方案2】:如果父集和子集都很大,'EXISTS' 可以比'IN' 工作得更快。
因为对于大型集合,O(n*log(n)) 比 O(n*n) 快如果子集很小,'EXISTS' 的工作速度可能比 'IN' 慢。
由于查询结构和由此产生的查询计划更改;例如慢 30%(1.5s)。【讨论】:
以上是关于Jdbc execute 比工具速度慢的主要内容,如果未能解决你的问题,请参考以下文章
为啥带有'exists'的sql运行速度比使用MySQL的'in'慢