(点击
上方蓝字
,快速关注我们)
来源:暗夜在火星
链接:my.oschina.net/dogstar/blog/398879
背景
前几天在项目上线过程中,发现有一个页面无法正确获取数据,经排查原来是接口调用超时,而最后发现是因为SQL查询长达到20多秒而导致了问题的发生。
这里,没有高深的理论或技术,只是备忘一下经历和解读一些思想误区。
复杂SQL语句的构成
这里不过多对业务功能进行描述,但为了突出问题所在,会用类比的语句来描述当时的场景。复杂的SQL语句可以表达如下:
SELECT
*
FROM
a_table
AS
a
LEFT
JOIN
b_table
AS
b
ON
a.id
=
b.id
WHERE
a.id
IN
(
SELECT
DISTINCT
id
FROM
a_table
WHERE
user_id
IN
(100,102,103)
GROUP
BY
user_id
HAVING
count
(id)
>
3
)
关联查询
从上面简化的SQL语句,可以看出,首先进行的是关联查询。
子查询
其次,是嵌套的子查询。此子查询是为了找出多个用户共同拥有的组ID。所以语句中的“100,102,103”是根据场景来定的,并且需要和后面“count(id) > 3”的个数对应。简单来说,就是找用户交集的组ID。
耗时在哪?
假设现在a_table表的数据量为20W,而b_table的数据量为2000W。大家可以想一下,你觉得主要的耗时是在关联查询部分,还是在子查询部分?
(思考空间。。。。)
(思考空间。。。。 。。。)
(思考空间。。。。 。。。 。。。)
问题定位
对于SQL底层的原理和高深的理论,我暂时掌握不够深入。但我知道可以通过类比和简单的测试来验证是哪一块环节出了问题。
初步断定
首先,对于只有一个用户ID时,我会把上面的语句简化成:
SELECT
*
FROM
a_table
AS
a
LEFT
JOIN
b_table
AS
b
ON
a.id
=
b.id
WHERE
user_id
IN
(100)
所以,初步断定应该是嵌套的子查询部分占用了大部分的时间。
再进一步验证
既然定位到了是嵌套的子查询语句的问题,那又要分为两块待排查的区域:是子查询本身耗时大,还是嵌套而导致慢查询?