zoukankan      html  css  js  c++  java
  • 慢查询SQL优化

    记一次慢查询的SQL优化

    测试表结构
    MariaDB [shoppings]> desc login_userinfo;
    +------------+-------------+------+-----+---------+----------------+
    | Field      | Type        | Null | Key | Default | Extra          |
    +------------+-------------+------+-----+---------+----------------+
    | num        | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name       | varchar(16) | NO   | UNI | NULL    |                |
    | password   | varchar(40) | NO   |     | NULL    |                |
    | nickname   | varchar(16) | NO   |     | NULL    |                |
    | sex        | varchar(10) | NO   |     | NULL    |                |
    | settime    | datetime(6) | NO   |     | NULL    |                |
    | addr       | varchar(32) | NO   |     | NULL    |                |
    | email      | varchar(32) | NO   |     | NULL    |                |
    | phone      | varchar(11) | NO   |     | NULL    |                |
    | receiver   | varchar(64) | NO   |     | NULL    |                |
    | code       | varchar(6)  | NO   |     | NULL    |                |
    | comment_id | int(11)     | YES  | MUL | NULL    |                |
    +------------+-------------+------+-----+---------+----------------+
    12 rows in set (0.003 sec)
    
    表中数据量
    MariaDB [shoppings]> select count(*) from login_userinfo;
    +----------+
    | count(*) |
    +----------+
    | 11809884 |
    +----------+
    1 row in set (2.503 sec)
    

    分页

    MariaDB [shoppings]> select u.num, u.name, u.nickname, u.settime, u.addr,c.content from login_userinfo as u inner join login_comment as c on u.comment_id=c.id limit 10000000, 10;
    +----------+--------------+--------------+----------------------------+------+---------+
    | num      | name         | nickname     | settime                    | addr | content |
    +----------+--------------+--------------+----------------------------+------+---------+
    | 20010049 | test20014998 | test20014998 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    | 20010050 | test20014999 | test20014999 | 2021-02-20 00:00:00.000000 | 北京 | 不太行  |
    | 20010051 | test20015000 | test20015000 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010052 | test20015001 | test20015001 | 2021-02-20 00:00:00.000000 | 北京 | 不太行  |
    | 20010053 | test20015002 | test20015002 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010054 | test20015003 | test20015003 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    | 20010055 | test20015004 | test20015004 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010056 | test20015005 | test20015005 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010057 | test20015006 | test20015006 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    | 20010058 | test20015007 | test20015007 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    +----------+--------------+--------------+----------------------------+------+---------+
    10 rows in set (1 min 6.340 sec)
    

    这次查询需要1分6秒,很明显当数据量过大时 查询效率会直线下降 ,使用者毫无体验(#-_-)

    MariaDB [shoppings]> explain select u.num, u.name, u.nickname, u.settime, u.addr,c.content from login_userinfo as u inner join login_comment as c on u.comment_id=c.id limit 10000000, 10;
    

    查看执行计划会看到它可能进行了全表扫描

    MariaDB [shoppings]> explain select u.num, u.name, u.nickname, u.settime, u.addr,c.content from login_userinfo as u inner join login_comment as c on u.comment_id=c.id limit 10000000, 10;
    +------+-------------+-------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+----------------+--------+-------------+
    | id   | select_type | table | type  | possible_keys                                          | key                                                    | key_len | ref            | rows   | Extra       |
    +------+-------------+-------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+----------------+--------+-------------+
    |    1 | SIMPLE      | c     | index | PRIMARY                                                | content                                                | 380     | NULL           | 17     | Using index |
    |    1 | SIMPLE      | u     | ref   | Login_userinfo_comment_id_3d2eced3_fk_Login_comment_id | Login_userinfo_comment_id_3d2eced3_fk_Login_comment_id | 5       | shoppings.c.id | 681715 |             |
    +------+-------------+-------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+----------------+--------+-------------+
    2 rows in set (0.001 sec)
    

    优化

    查询主键num值

    MariaDB [shoppings]> select num from login_userinfo limit 10000000,1;
    +----------+
    | num      |
    +----------+
    | 20010043 |
    +----------+
    1 row in set (3.259 sec)
    
    MariaDB [shoppings]> explain select num from login_userinfo limit 10000000,1;
    +------+-------------+----------------+-------+---------------+--------------------------------------------------------+---------+------+----------+-------------+
    | id   | select_type | table          | type  | possible_keys | key  | key_len | ref  | rows     | Extra       |
    +------+-------------+----------------+-------+---------------+--------------------------------------------------------+---------+------+----------+-------------+
    |    1 | SIMPLE      | login_userinfo | index | NULL          | Login_userinfo_comment_id_3d2eced3_fk_Login_comment_id | 5       | NULL | 10907448 | Using index |
    +------+-------------+----------------+-------+---------------+--------------------------------------------------------+---------+------+----------+-------------+
    1 row in set (0.000 sec)
    

    虽然我们也进行了全表扫描,但是我们用的是主键索引,所以效率会更高。

    通过主键num值,查询

    MariaDB [shoppings]> select u.num, u.name, u.nickname, u.settime, u.addr,c.content from login_userinfo as u inner join login_comment as c on u.comment_id=c.id where u.num>20010043 limit 10;
    +----------+--------------+--------------+----------------------------+------+---------+
    | num      | name         | nickname     | settime                    | addr | content |
    +----------+--------------+--------------+----------------------------+------+---------+
    | 20010045 | test20014994 | test20014994 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    | 20010046 | test20014995 | test20014995 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010047 | test20014996 | test20014996 | 2021-02-20 00:00:00.000000 | 北京 | 不太行  |
    | 20010048 | test20014997 | test20014997 | 2021-02-20 00:00:00.000000 | 上海 | 不太行  |
    | 20010049 | test20014998 | test20014998 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    | 20010050 | test20014999 | test20014999 | 2021-02-20 00:00:00.000000 | 北京 | 不太行  |
    | 20010051 | test20015000 | test20015000 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010052 | test20015001 | test20015001 | 2021-02-20 00:00:00.000000 | 北京 | 不太行  |
    | 20010053 | test20015002 | test20015002 | 2021-02-20 00:00:00.000000 | 广州 | 不太行  |
    | 20010054 | test20015003 | test20015003 | 2021-02-20 00:00:00.000000 | 深圳 | 不太行  |
    +----------+--------------+--------------+----------------------------+------+---------+
    10 rows in set (0.020 sec)
    
    MariaDB [shoppings]> explain select u.num, u.name, u.nickname, u.settime, u.addr,c.content from login_userinfo as u inner join login_comment as c on u.comment_id=c.id where u.num>20010044 limit 10;
    +------+-------------+-------+--------+----------------------------------------------------------------+---------+---------+------------------------+---------+-------------+
    | id   | select_type | table | type   | possible_keys                                                  | key     | key_len | ref                    | rows    | Extra       |
    +------+-------------+-------+--------+----------------------------------------------------------------+---------+---------+------------------------+---------+-------------+
    |    1 | SIMPLE      | u     | range  | PRIMARY,Login_userinfo_comment_id_3d2eced3_fk_Login_comment_id | PRIMARY | 4       | NULL                   | 3638072 | Using where |
    |    1 | SIMPLE      | c     | eq_ref | PRIMARY                                                        | PRIMARY | 4       | shoppings.u.comment_id | 1       |             |
    +------+-------------+-------+--------+----------------------------------------------------------------+---------+---------+------------------------+---------+-------------+
    

    我们先拿到主键num的值 ,再通过num 进行查询。通过这两次查询 时间不到4秒。效率大大提升。

    此时此刻,非我莫属
  • 相关阅读:
    【长安十二时辰】 刺客信条风格剪辑
    【Oracle 触发器】(6)触发器应用场景--数据的备份和同步
    【Oracle 触发器】(5)触发器应用场景--数据库的审计
    银行窗口取号系统,共享数据的线程安全性
    模板方法
    创建线程时如果既传入了runnable对象,又继承thread重写了run方法,会执行哪里的代码
    启动线程用start方法而不是run方法
    java的回调
    java中的闭包
    静态内部类
  • 原文地址:https://www.cnblogs.com/taozhengquan/p/14878230.html
Copyright © 2011-2022 走看看