MySQL查询在新服务器上花费太多时间

时间:2017-10-11 03:24:11

标签: mysql optimization mariadb

我在2台服务器上拥有相同的数据库。

服务器1(云服务器4 GB RAM)

MySQL变量= https://pastebin.com/raw/jENsXnsK

这是一个云服务器(来自rackspace的托管MySQL云实例),具有4 GB的RAM。

当我执行查询时,它有多个JOINS,它在

中执行
150 rows in set (0.61 sec)

服务器2(专用32 GB RAM)

MySQL变量= https://pastebin.com/raw/sYdBhp4p

这是一个新的专用服务器,具有32 GB的内存。尚未投入生产,我们正在尝试将云服务器移至专用,因为我们获得了更多的CPU / RAM。

将数据库从云服务器复制到这个新的专用,但相同的查询需要更多时间。

150 rows in set (21.32 sec)

这比慢了大约40倍。

专用

上的free -m结果
[root@server1 ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:          31797        2700       23182          96        5914       28569
Swap:         16381           0       16381
[root@server1 ~]# 

在云中没有ssh访问权限,只需像Amazon RDS那样访问MySQL。

编辑1:

我将join_buffer_size从默认值131072更改为2M,这使得查询在专用服务器上执行得更快。

  

150行(1.84秒)

仍然比使用4GB RAM的服务器慢约3倍。

(来自link + prettyprint)

SELECT  nr.*, p.*, e.*, 
    (
        SELECT  cityname as cityname
            FROM  city_type AS ct
            where  ct.id = p.city_type
    ) as cityname, 
    (
        SELECT  city_id as city_id
            FROM  tbl_suburb AS ts
            where  ts.id = e.tbl_suburb_id
    ) as suburb_city_id, 
    (
        SELECT  suburb_name
            FROM  tbl_suburb AS ts
            where  ts.id = e.tbl_suburb_id
    ) as suburb_name, 
    (
        SELECT  kilometers as km
            FROM  tbl_suburb AS tskm
            where  tskm.id = e.tbl_suburb_id
    ) as suburb_kilometers
    FROM  new_registrations AS nr
    INNER JOIN  tbl_admin_registrations AS tar  ON tar.registration_id = nr.id
    INNER JOIN  tbl_admin_properties AS tap  ON tap.admin_id = tar.admin_id
    INNER JOIN  (tbl_properties AS p
            LEFT JOIN  tbl_room_types rt  ON (rt.tbl_property_id = p.id)
                )  ON p.id = tap.property_id
    INNER JOIN  tbl_expansions AS e  ON e.property_id = tap.property_id
    WHERE  p.expansion = '1'
      AND  p.status = '2'
      AND  nr.country = 1
      AND  nr.id NOT IN( 203, 204 )
      AND  ( nr.deleted = 'n'
              OR  nr.deleted IS NULL 
           )
      AND  e.id IN (
        SELECT  te.id as expansion_id
            FROM  tbl_suburb AS ts2
            INNER JOIN  tbl_expansions as te  ON te.tbl_suburb_id IN (
                SELECT  id
                    FROM  tbl_suburb
                    WHERE  city_id IN (
                        SELECT  id
                            FROM  city_type
                            WHERE  country_id = '1')) 
                          )AND (
                  (rt.week4 > 350 AND  rt.week4 <= 5250 )
              OR  (rt.week3 > 350 AND  rt.week3 <= 5250 )
              OR  (rt.week2 > 350 AND  rt.week2 <= 5250 )
              OR  (rt.week1 > 350 AND  rt.week1 <= 5250 ) )
    GROUP BY  nr.id;

1 个答案:

答案 0 :(得分:0)

  • 尽可能将IN ( SELECT ... )变为JOIN。我看到这样的嵌套3深陷畏缩。

  • 尝试首先获取所需的ID ,然后加入其他表。这可以避免JOIN + GROUP BY的“爆炸内爆”成本。

  • 'n'IS NULL之间选择deleted。使用OR可能会导致效率低下。

  • week1..week4:在列之间展开数组通常是一个坏主意。在这种情况下,它会导致无法优化的OR

  • join_buffer_size太小了。但是JOIN缓冲区可以解决上述一些问题。

  • 所有JOIN都可以使用索引吗? (EXPLAIN并不明显。请提供SHOW CREATE TABLEs