在公司的项目里面遇到了一个情况,是一个列表的 SQL 查询,我写好 SQL 直接丢进 MySQL 执行,查询时间是 0.469s
在放进 MyBatis 实际执行的过程中发现分页插件在 SQL 我写的 SQL 的外围再包了一层select count(1) from ()
以后查询就变得巨慢,几十秒都出不来结果。。。😂
然后我在调试过程中发现如果把原 SQL 中的where
语句都删掉,放进外包一层select count(1) from()
以后查询就变得正常了,查询时间是 0.755s
现在就很好奇这是为什么以及这种外包一层 select 导致查询巨慢的情况需要怎么解决?网上搜了一下,找不到什么有用的资讯,数据库方面有点菜,因此来请教下各位 v2 的大佬,谢谢!
1
zjlletian 2019-09-20 17:49:20 +08:00
可能是包了一层就不走索引了?? explain 看看
|
2
LlvlDd 2019-09-20 17:54:22 +08:00
使用 count(*) 有神秘加成
|
3
grittiness OP @zjlletian 要是执行原本带了 where 的 SQL,explain 能一直执行到数据库强制断开连接都出不来结果,如果我去掉 where 用 explain 看的话是有走索引的
|
4
grittiness OP @LlvlDd count(*) 也一样 出不来结果
|
5
Vegetable 2019-09-20 18:01:46 +08:00
可以尝试搜索 子查询 索引失效 这两个关键字哦
|
6
StarkWhite 2019-09-20 18:02:07 +08:00
应该是子查询临时表问题,不加 WHERE 会被查询引擎优化成没有子查询的语句,
不过这也只是推测,具体的 SQL 语句发出来看看呗 |
7
Rekkles 2019-09-20 18:02:59 +08:00
100ms 都慢了 你这 几百毫秒 ... 我很好奇你说的变慢是多慢
|
8
grittiness OP @Rekkles left join 了 20 张表,还有 group by,所以感觉 1m 以内没啥问题把
@StarkWhite SQL 太复杂了,不太合适发上来,left join 了 20 张表,可以私发给你看看。。 |
9
chengyiqun 2019-09-20 18:32:05 +08:00
这个之前我也碰到过, 通过客户名称定位客户时, 本来就是模糊查询(不走索引) 包一层更慢. 索性手动分页, 计算好 limit 和 offset... 快多了, 原本直接服务超时, 改过以后, 400ms.
```java Integer count; if ( ( "2".equals(qryInMap.get("custTypeFlag")) || "3".equals(qryInMap.get("custTypeFlag")) ) && ( !ObjectIsNull.check(qryInMap.get(Constants.HUMP_PROD_INST_ID)) || !ObjectIsNull.check(qryInMap.get(Constants.HUMP_ACC_NBR)) || !ObjectIsNull.check(qryInMap.get(Constants.HUMP_ACCOUNT)) ) ) { List<Long> custIdsList1 = this.selectList(null, QRY_CUST_LIST_NAME_SPACE + ".qryUseCustIdsOrPayCustIdsByProdInst", qryInParamMap); qryInParamMap.put("custIds", custIdsList1); qryInParamMap.remove(Constants.HUMP_PROD_INST_ID); qryInParamMap.remove(Constants.HUMP_ACC_NBR); qryInParamMap.remove(Constants.HUMP_ACCOUNT); qryInParamMap.remove("custTypeFlag"); count = this.selectOne(null, QRY_CUST_LIST_NAME_SPACE + ".countCustWithoutParam", qryInParamMap); } else { count = this.selectOne(null, QRY_CUST_LIST_NAME_SPACE + ".countCustWithoutParam", qryInParamMap); } if (pageMap != null) { pageMap.setTotalRecord(count); pageMap.setTotalPage(count % pageMap.getPageSize() == 0? count/pageMap.getPageSize() : count/pageMap.getPageSize() + 1); if (count == 0 || (pageMap.getStartNum() > count)) { return new ArrayList<Map<String,Object>>(); } qryInParamMap.put("startNum", pageMap.getStartNum()); qryInParamMap.put("pageSize", pageMap.getPageSize()); } else { // 兼容政企客户类型不传 分页 if (count == 0) { return new ArrayList<Map<String,Object>>(); } qryInParamMap.put("startNum", 0); qryInParamMap.put("pageSize", 65535); } List<Long> custIdsList = this.selectList(null, QRY_CUST_LIST_NAME_SPACE + ".queryCustIdsWithoutParam", qryInParamMap); qryInParamMap.put("custIds", custIdsList); List<Map<String, Object>> customers = this.selectList(null, QRY_CUST_LIST_NAME_SPACE + ".queryCustListWithCustIds", qryInParamMap); ``` |
10
StarkWhite 2019-09-21 10:18:43 +08:00
@grittiness SQL 复杂和私发有啥关系?如果说格式问题,复制粘贴到能格式化 SQL 的工具就好了。
而且我不一定能帮你解决哦,发出来可能别的 V 友会帮你解决 |
11
grittiness OP |
12
StarkWhite 2019-09-21 15:03:36 +08:00
@grittiness 把表名换掉,字段名也可以换掉
|