mysql多表关联查询分页如何优化?-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

mysql多表关联查询分页如何优化?

2015-04-23 11:23:05 22872 4

请问各位大神,我用mysql关联查询,limit进行分页 ,但是当数据过万时翻页就特别慢,请问有什么好的优化办法啊?
我的代码:


      SELECT
    c0.c_custnum AS cCustnum,
    c0.c_username AS cUsername,
    
        c10.cust_rank AS custRank,
        jifen30.rank_name AS rankName,
        c10.c_accdate AS cAccdate,
        c10.c_custname AS cCustname

      FROM
    capf00 AS c0
      LEFT JOIN capf10 AS c10 ON c0.c_custnum = c10.c_custnum
      LEFT JOIN capf30 AS c30 ON (c10.c_custnum = c30.c_custnum AND c30.is_del = 'N')
      LEFT JOIN capf120 ON capf120.cust_no = c10.c_custnum
      LEFT JOIN jifen30 ON c10.cust_rank = jifen30.cust_rank
     LEFT JOIN capf101 ON capf101.cust_no = c0.c_custnum

     WHERE
      capf120.create_time IS NULL
   AND c0.is_del = 'N'
   AND c10.is_del = 'N'


   LIMIT 9500 OFFSET 10
取消 提交回答
全部回答(4)
  • hansen1160
    2015-05-04 09:31:18
    回6楼俞月的帖子
    谢谢了,这是我简化了的,原来有6,7个表。谢谢大哥!
    0 0
  • hansen116
    2015-04-24 15:48:56
    回1楼俞月的帖子
    谢谢大哥指教


    可是改变驱动表结果也变了啊,capf00是一个客户基本信息表,
    其他表是客户各种信息,这个查询语句就是要查 “全部客户”  的 “所有信息” 啊

    -------------------------

    回4楼俞月的帖子
       那您的意思不用改sql语句,只增加适当的索引就行了吗  实在有点不理解,谢谢大哥耐心指教
    0 0
  • 惠路由
    2015-04-24 13:36:30
    Remysql多表关联查询分页如何优化?
    好好学习一下
    0 0
  • 俞月
    2015-04-24 12:03:11
    Remysql多表关联查询分页如何优化?
    这里涉及到两部分的优化,多表关联和Limit分页。


    SQL优化依赖于表中的数据分布,explain得到的执行计划中的rows可以大致反映出问题所在。由于现在只能看到您提供的SQL,没有具体的数据信息,我就说一下,拿到这条SQL后,我的优化思路:


    多表关联的优化原则是小结果集驱动大结果集。这个阶段的优化非常重要,一般按照下面的步骤进行分析:
    1. 确定驱动表,通过explain查看执行计划,可以看到优化器选择的驱动表。explain结果中,第一行出现的表就优化器选择的驱动表。


    SELECT
        c0.c_custnum AS cCustnum,
        c0.c_username AS cUsername,

            c10.cust_rank AS custRank,
            jifen30.rank_name AS rankName,
            c10.c_accdate AS cAccdate,
            c10.c_custname AS cCustname

          FROM
        capf00 AS c0
          LEFT JOIN capf10 AS c10 ON c0.c_custnum = c10.c_custnum
          LEFT JOIN capf30 AS c30 ON (c10.c_custnum = c30.c_custnum AND c30.is_del = 'N')
          LEFT JOIN capf120 ON capf120.cust_no = c10.c_custnum
          LEFT JOIN jifen30 ON c10.cust_rank = jifen30.cust_rank
         LEFT JOIN capf101 ON capf101.cust_no = c0.c_custnum

         WHERE
       capf120.create_time IS NULL
       AND c0.is_del = 'N'
       AND c10.is_del = 'N'


    一般,习惯性认为left join驱动顺序是固定的,left join左边的表为驱动表,右边为被驱动表。
    其实这也不是绝对的,当left join跟inner join等价的时候,MySQL优化器就会自己选择驱动表。
    MySQL对表连接至今只支持nested loop join,通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果集。优化的目标是尽可能减少关联查询中nested loop的循环次数,也就是说尽量缩小驱动表的结果集。


    2. 理清各表之间的关联关系,注意被驱动表的关联字段上需要建立索引
    假设在第1步中,最后选取的驱动表是c0, 那么根据表关联关系,可以理出驱动顺序为
    c0 -> c10 ->c30 ;  c10->capf120;  c10 ->jfen30 ;c0 ->capf101;
    那么在被驱动表的关联字段上,是需要建立索引的,这里包括:
    c10.c_custnum
    c30.c_custnum
    capf120.cust_no
    jifen30.cust_rank
    capf101.cust_no


    3. 综合考虑join字段和where字段,那么:
    c0建立索引 (is_del)
    c10建立组合索引 (c_custnum,is_del)
    c30建立组合索引 (c_custnum,is_del)
    capf120建立组合索引 (cust_no,create_time)
    jifen30建立索引 (cust_rank)
    capf101建立索引 (cust_no)

    limit 分页的优化:
    可以利用到覆盖索引,使得在查询时,直接从二级索引中获取结果,避免返回数据行查找;
    4. 所以结合到 select 字段,进一步优化索引:
    SELECT
        c0.c_custnum AS cCustnum,
        c0.c_username AS cUsername,

            c10.cust_rank AS custRank,
            jifen30.rank_name AS rankName,
            c10.c_accdate AS cAccdate,
            c10.c_custname AS cCustname

    结合上面的几个步骤,最后给出的索引建议是:(这里依赖了前文中的一个假设条件,具体情况还是要依赖实际数据)
    c0 建立组合索引(is_del,c_custnum,c_username)
    c10 建立组合索引(c_custnum,is_del,cust_rank,c_accdate,c_custname)
    c30 建立组合索引 (c_custnum,is_del)
    capf120 建立组合索引(cust_no,create_time)
    jifen30 建立组合索引(cust_rank,rank_name)
    capf101 建立索引(cust_no)

    -------------------------

    回3楼hansen116的帖子

    业务逻辑,是通过SQL来实现的。驱动表是MySQL优化器去选择的。随着建立的索引不同,数据分布的不同,对于同样的SQL语句,MySQL优化器可能选择不同的驱动表。








    -------------------------

    回5楼hansen116的帖子
    对的,只需要添加索引就行了。

    另外,看到您的SQL语句其实只查询了3个表(c0,c10,jifen30)中的字段,但是查询了6个表中的关联。
    您可以确认下,是否其他的几个表关联也都是业务上必要的。
    如果不需要,可以减少表关联,可以提高查询效率的。
    0 0
添加回答
相关问答

1

回答

【RDS】RDS MySQL如何终止会话?

2022-01-12 16:17:02 450浏览量 回答数 1

1

回答

RDS MySQL如何终止会话?

2022-01-07 14:15:23 876浏览量 回答数 1

0

回答

技术运维问题 - MYSQL使用 -RDS for MySQL 从传输流收到意外的 EOF或0个字节

2018-09-28 22:31:04 3487浏览量 回答数 0

0

回答

技术运维问题 - MYSQL使用 -RDS MySQL 收集表的统计数据

2018-09-28 22:34:39 1773浏览量 回答数 0

0

回答

技术运维问题 - MYSQL使用 -RDS MySQL实例重启后表不能访问

2018-09-28 22:39:35 1635浏览量 回答数 0

1

回答

mysql rds通过主键更新数据,执行计划为什么走的是range方式

2018-09-27 21:10:13 3604浏览量 回答数 1

1

回答

RDS mysql binlog 模式是什么?

2018-09-28 11:24:56 457浏览量 回答数 1

0

回答

技术运维问题 - MYSQL使用 -RDS for MySQL 实例 show slave hosts 结果说明

2018-09-26 23:29:03 1969浏览量 回答数 0

0

回答

技术运维问题 - MYSQL使用 -RDS for MySQL 连接数满情况的处理

2018-09-26 23:36:07 2018浏览量 回答数 0

0

回答

技术运维问题 - MYSQL使用 -RDS for MySQL CPU使用率高情况的原因和解决

2018-09-26 23:38:27 1665浏览量 回答数 0
+关注
0
文章
2
问答
问答排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载