Rows_sent:12 Rows_examined:549024 - 如何优化mySQL查询?

时间:2012-08-04 23:30:29

标签: mysql performance optimization

我有一个数据库,列出了相当不错的服务器(四核Xeon 2.0Ghz,16GB RAM,SSD驱动器)。该数据库有大约180,000个列表。服务器上还没有流量,我只是用大量的列表测试它,以确保以后没有任何问题,实际上有很多实时列表和实际流量。

但即使没有交通,我觉得他们应该比实际回来更快。

从慢查询日志中,我找到了这个:

# Query_time: 1.575742  Lock_time: 0.000113 Rows_sent: 12  Rows_examined: 549024

有180,000条记录,它只需要返回12条,但它会检查超过500,000条,需要超过1.5秒?有些事情必须是错的,对吧? :(

实际查询是:

SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
     a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
     a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
     a.is_relisted_item, a.enable
     FROM db_listings a
     LEFT JOIN db_users u ON u.user_id=a.owner_id  WHERE a.active=1 AND
     a.approved=1 AND a.deleted=0 AND a.creation_in_progress=0 AND
     a.closed=0 AND (a.list_in='store' OR u.shop_active='1')
     GROUP BY a.listing_id
     ORDER BY a.list_in ASC, a.end_time ASC  LIMIT 0, 12;

已在db_listings中的listing_id以及db_users中的user_id上设置索引。我不认为db_users join是一个问题,因为现在只有2个用户。

如果您需要任何其他信息来解决此问题,请告诉我们。

非常感谢任何帮助:)

1 个答案:

答案 0 :(得分:1)

首先,您的查询存在问题。您使用LEFT JOIN,但是使用where子句转换为隐式INNER JOIN:     AND(a.list_in ='store'或u.shop_active ='1')

为什么这会将LEFT JOIN变为隐式INNER?因为当没有匹配的用户时,LEFT JOIN将为u.shop_active产生NULL值,但NULL将永远不等于'1'。这会将查询转换为INNER JOIN,因为OUTER JOIN生成的任何行都将被WHERE条件过滤。

此过滤器也是性能问题的原因。在两个不同的表中的列之间有OR条件。没有索引可以满足这样的条件。

这是另一种可能表现更好的方式。当版本少于12个list_in ='store'列表时,此版本将仅搜索其中的列表(a.list_in!='store'和u.shop_active ='1')。

要使用以下内容,确保您有一个索引(list_in,end_time)

SELECT * FROM
(
    SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
           a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
           a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
           a.is_relisted_item, a.enable
     FROM db_listings a
    WHERE list_in = 'store'
     a.active=1 AND
     a.approved=1 AND 
     a.deleted=0 AND 
     a.creation_in_progress=0 AND
     a.closed=0
    ORDER BY end_time 
    LIMIT 12 
    )
    UNION ALL
    (
        SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
           a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
           a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
           a.is_relisted_item, a.enable
        FROM db_listings a
        JOIN users u 
          ON a.owner_id = u.user_id
         AND u.shop_active = '1'
       WHERE list_in != 'store' AND
       a.active=1 AND
       a.approved=1 AND 
       a.deleted=0 AND 
       a.creation_in_progress=0 AND
       a.closed=0
       ORDER BY end_time 
       LIMIT 12 
    )
) sq
ORDER BY list_in, end_time
LIMIT 12;