zoukankan      html  css  js  c++  java
  • 记一条sql语句优化

     傻瓜级的。此sql语句存在于分销王系统中。

    查阅slow log ,时间设置1s

    发现很多

    SELECT r.*, goods_id, bn, name FROM sdb_goods_rate r, sdb_goods
    WHERE ((goods_2 = goods_id AND goods_1=4799) OR (goods_1 = goods_id AND goods_2 = 4799 AND manual='both')) AND rate > 99;

    主要是2个表的联立,相当于inner join吧。 条件是 goods_2= xx and goods_1=zz

    mysql> show create table sdb_goods_rate;
    -------------------------------------------------------------------------------------+
    | sdb_goods_rate | CREATE TABLE `sdb_goods_rate` (
    `goods_1` mediumint(8) unsigned NOT NULL,
    `goods_2` mediumint(8) unsigned NOT NULL,
    `manual` enum('left','both') DEFAULT NULL,
    `rate` mediumint(8) unsigned NOT NULL DEFAULT '1',
    PRIMARY KEY (`goods_1`,`goods_2`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 |

    可以看到goods_rate 的primary key 是 goods_1 ,goods_2 而我们用到的查询是 goods_2 ,goods_1 ,用不上我们的pk 索引。

    这点可以从explain里面来观察。

    mysql> explain SELECT r.*, goods_id, bn, name FROM sdb_goods_rate r, sdb_goods
    -> WHERE ((goods_2 = goods_id AND goods_1=2708) OR (goods_1 = goods_id AND goods_2 = 2708 AND manual='both')) AND rate > 99;
    +----+-------------+-----------+------+---------------+------+---------+------+-------+--------------------------------+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +----+-------------+-----------+------+---------------+------+---------+------+-------+--------------------------------+
    | 1 | SIMPLE | sdb_goods | ALL | PRIMARY | NULL | NULL | NULL | 3024 | |
    | 1 | SIMPLE | r | ALL | PRIMARY | NULL | NULL | NULL | 23109 | Using where; Using join buffer |
    +----+-------------+-----------+------+---------------+------+---------+------+-------+--------------------------------+

    扫描都是all 全表扫描,产生了笛卡尔积,大概是 3000*23000 约等于69000000,非常大的一个数据量。

    我们这里创建索引

    create index idx_goods12 on sdb_goods_rate(goods_2,goods_1);

    然后再看执行计划,

    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    | 1 | SIMPLE | r | index_merge | PRIMARY,idx_goods12 | PRIMARY,idx_goods12 | 3,3 | NULL | 38 | Using sort_union(PRIMARY,idx_goods12); Using where |
    | 1 | SIMPLE | sdb_goods | ALL | PRIMARY | NULL | NULL | NULL | 3024 | Range checked for each record (index map: 0x1) |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+

    数据量大大减少,为38*3024=120000,数据量规模大概小了575倍,基本上0.1秒都不用,结果就出来了。

  • 相关阅读:
    摩托罗拉SE4500 德州仪器TI Omap37xx/AM3715/DM3730/AM3530 wince6.0/Windows Mobile 6.5平台 二维软解调试记录及相关解释
    摩托罗拉SE4500 三星 S3C6410 Wince6.0平台软解码调试记录以及驱动相关问题解释
    MSM8909+Android5.1.1之系统烧录
    PIC16F914SEG脚中电路图注意事项
    PIC16F914ADC模块采集数据转换
    PIC914AD模块使用记录
    PIC914 LCDCON液晶控制寄存器用法
    PIC914SEG设置方法
    示波器用法
    检测单片机是否启动
  • 原文地址:https://www.cnblogs.com/gqdw/p/3163510.html
Copyright © 2011-2022 走看看