MySQL 查询在原本的 SQL 外再包一层就会导致查询巨慢有什么解决方式么?

2019-09-20 17:40:30 +08:00
 grittiness

在公司的项目里面遇到了一个情况,是一个列表的 SQL 查询,我写好 SQL 直接丢进 MySQL 执行,查询时间是 0.469s

在放进 MyBatis 实际执行的过程中发现分页插件在 SQL 我写的 SQL 的外围再包了一层select count(1) from ()以后查询就变得巨慢,几十秒都出不来结果。。。😂

然后我在调试过程中发现如果把原 SQL 中的where语句都删掉,放进外包一层select count(1) from()以后查询就变得正常了,查询时间是 0.755s

现在就很好奇这是为什么以及这种外包一层 select 导致查询巨慢的情况需要怎么解决?网上搜了一下,找不到什么有用的资讯,数据库方面有点菜,因此来请教下各位 v2 的大佬,谢谢!

4910 次点击
所在节点    MySQL
12 条回复
zjlletian
2019-09-20 17:49:20 +08:00
可能是包了一层就不走索引了?? explain 看看
LlvlDd
2019-09-20 17:54:22 +08:00
使用 count(*) 有神秘加成
grittiness
2019-09-20 17:56:44 +08:00
@zjlletian 要是执行原本带了 where 的 SQL,explain 能一直执行到数据库强制断开连接都出不来结果,如果我去掉 where 用 explain 看的话是有走索引的
grittiness
2019-09-20 17:57:34 +08:00
@LlvlDd count(*) 也一样 出不来结果
Vegetable
2019-09-20 18:01:46 +08:00
可以尝试搜索 子查询 索引失效 这两个关键字哦
StarkWhite
2019-09-20 18:02:07 +08:00
应该是子查询临时表问题,不加 WHERE 会被查询引擎优化成没有子查询的语句,
不过这也只是推测,具体的 SQL 语句发出来看看呗
Rekkles
2019-09-20 18:02:59 +08:00
100ms 都慢了 你这 几百毫秒 ... 我很好奇你说的变慢是多慢
grittiness
2019-09-20 18:19:01 +08:00
@Rekkles left join 了 20 张表,还有 group by,所以感觉 1m 以内没啥问题把
@StarkWhite SQL 太复杂了,不太合适发上来,left join 了 20 张表,可以私发给你看看。。
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);

```
StarkWhite
2019-09-21 10:18:43 +08:00
@grittiness SQL 复杂和私发有啥关系?如果说格式问题,复制粘贴到能格式化 SQL 的工具就好了。
而且我不一定能帮你解决哦,发出来可能别的 V 友会帮你解决
grittiness
2019-09-21 14:35:38 +08:00
@StarkWhite 因为是公司的代码,我怕发上来不太合适.... 😂
@chengyiqun 谢谢 学习下
StarkWhite
2019-09-21 15:03:36 +08:00
@grittiness 把表名换掉,字段名也可以换掉

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/602628

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX