关于海量数据表的分页性能问题调试记录(mysql left join的性能分析)

最近开发一个订单系统,其中涉及订单列表显示的页面,在数据量达到10万级以上的时候,页面刷新超级慢,几乎可以打到30秒左右,而且点击某个分页也是反应及其慢,经过一段时间定位,发现问题所在,特此记录下来供大家参考。

一、业务需求简介:

涉及的表及其之间的关系如下:


要显示的表为订单表(大概20万条数据),同时每条记录需要显示客户姓名和供货商姓名,这样就需要通过订单表中的客户ID/供货商ID作为外键分别访问到客户表和供货商表,其中客户表中有2条数据,供货商表中有7条数据。

分页显示的订单表每页显示30条数据,大概需要分6000多页。此时每页显示特别慢。

二、问题分析:

        由于订单列表页面是通过GENEXUS工具生成的,生成的每一页的MYSQL查询语句经查看后为类似如下形式:


    SELECT T1.ID,T1.xxx,T2.name as customer_name,T3.name as supplier_name 

    FROM ((`订单表` T1 LEFT JOIN `客户表` T2 ON T2.id=T1.客户ID)  LEFT JOIN `供货商表` T3 ON T3.id=T1.供货商ID) LIMIT begin_row,end_row

        可见这个sql用了两个LEFT JOIN把三张表联合起来,其中订单表(T1)是主表,使用LEFT JOIN的好处是当客户ID或国货商ID没有对应的记录时,该行订单也会显示出来,避免遗漏。

        上面这个SQL语句拿到SQL Manangerment Lite 里面执行,并分析执行时间和查询plan,发现这个sql语句执行了将近7-8秒,总查询次数为:T1记录数*T2记录数*T3记录数,即使做了外键或索引,总查询次数也至少为2*T1记录数。

        为什么会这样?我们来看上面的LEFT JOIN的执行细节:MYSQL先是将T1与T2进行LEFT JOIN,这样执行了将近20万次(T1记录数),生成一张临时表Temp1(20万条记录),然后这张临时表Temp1再与T3进行LEFT JOIN,生成一张临时表Temp2(20万条记录),然后对这个临时表Temp2进行分页查询(LIMIT语句),这样的速度不慢才怪!   

        然后又做了一个实验,使用下面能起到同样效果的SQL查询语句进行查询:

SELECT T1.ID,T1.xxx,T2.name as customer_name,T3.name as supplier_name  

FROM  (((SELECT ` 订单表` T1  LIMIT begin_row,end_row ) LEFT JOIN `客户表` T2 ON T2.id=T1.客户ID)  LEFT JOIN `供货商表` T3 ON T3.id=T1.供货商ID) 

     注意LIMIT的位置。

    上面这个SQL执行飞快,毫秒级别,迅速返回了同样的结果,上面这个SQL的执行细节为:MYSQL显示将T1进行分页查询(LIMIT语句找到某页的30条记录),查询结果生成临时表Temp1(30条记录),然后对这个临时表Temp1与T2进行LEFT JOIN,再进而与T3进行LEFT JOIN,总查询次数也不到100次!

三、问题解决方案:

        找到问题的原因之后,就可以又针对性的给出解决方案,由于使用的是GENEXUS自动生成这部分代码,所以先将GENEXUS中的GRID中删除【客户姓名】和【供货商姓名】这两个外链,同时过滤条件中也删除这两个外链的过滤,然后重新生成代码,检查生成代码中已经不再又LEFT JOIN语句了,仅仅是简单的SELECT FROM T1,此时运行WEB页面,发现翻页飞快。

        然后写了两个procedure,分别为GetCustomerNameById(customer_id),GetSupplierNameById(supplier_id),从名字上即可知道是根据两个id获得名字的过程,在过程里面分别查询客户表和供货商表,返回姓名即可。然后定义两个变量(客户姓名/供货商姓名)放到Grid里并显示出来,编译运行后,发现在页面上可以正常显示客户姓名和供货商姓名,同时翻页功能依然保持飞快!

至此问题解决!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值