怎样才能有一个好的EXPLAIN和一个慢查询?

时间:2012-05-16 14:13:48

标签: mysql performance

如何在EXPLAIN中制定一个好的计划,如下所示,查询速度慢。几行,使用索引,没有filesort。

查询在9s内运行。主表有大约500k行。

当我在该表中有250k行时,查询在< 1秒。

建议PLZ?

explain

查询(1.可以根据用户选择启用注释的字段.2。没有FORCE INDEX我得到14s.3。SQL_NO_CACHE我用来防止错误结果):

    SELECT SQL_NO_CACHE
          p.property_id
        , lct.loc_city_name_pt
        , lc.loc_community_name_pt
        , lc.loc_community_image_num_default
        , lc.loc_community_gmap_longitude
        , lc.loc_community_gmap_latitude
    FROM property as p FORCE INDEX (ix_order_by_perf)
    INNER JOIN loc_community lc 
        ON lc.loc_community_id = p.property_loc_community_id
    INNER JOIN loc_city lct FORCE INDEX (loc_city_id)
        ON lct.loc_city_id = lc.loc_community_loc_city_id
    INNER JOIN property_attribute pa
        ON pa.property_attribute_property_id = p.property_id        
    WHERE p.property_published = 1
        AND (p.property_property_type_id = '1' AND p.property_property_type_sale_id = '1') 
        AND p.property_property_housing_id = '1' 
--      AND p.property_loc_community_id = '36'  
--      AND p.property_bedroom_id = '2'
--      AND p.property_price >= '50000' AND p.property_price <= '150000'
--      AND lct.loc_city_id = '1'
--      AND p.property_loc_subcommunity_id IN(7,8,12) 
    ORDER BY 
          p.property_featured DESC
        , p.property_ranking_date DESC
        , p.property_ranking_total DESC
    LIMIT 0, 15

查询个人资料

query profile

结果集总是输出15行。但是table属性和property_attribute大约有500k行。

全心全意,

Armando Miani

4 个答案:

答案 0 :(得分:2)

在这种情况下,这在EXPLAIN中似乎很奇怪。这不会发生在MySQL 4.x上,但它确实发生在MySQL 5.x上。

MySQL真正向您展示的是MySQL正在尝试使用强制索引ix_order_by_perf对行进行排序,并且它显示15行,因为您有LIMIT 15。

但是,WHERE子句仍在扫描所有500K行,因为它不能在WHERE子句中使用索引作为条件。如果能够使用索引查找所需的行,您会在'possible_keys'字段中看到强制索引。

您可以通过保留FORCE INDEX子句并删除ORDER BY子句来证明这一点。您将看到My​​SQL现在不会使用任何索引,即使是您强制使用的索引(因为索引不能用于此目的)。

尝试将您在WHERE子句中引用的property_property_type_id,property_property_type_sale_id,property_property_housing_id和任何其他列添加到索引的开头。

答案 1 :(得分:1)

有一段时间,您的查询将针对某个模型进行优化,而该模型可能对某个特定需求不再有效。

计划可能很棒但是,即使您在where子句中使用的过滤器尊重索引定义,也不意味着解析器不会解析行。

您需要分析的是如何确定索引。例如,如果“人物”表中有“姓名,姓氏”的索引,如果每个人都有相同的姓名和姓氏,那么表演将会很糟糕。该指数是一个真正的陷阱,当它无法描述您的数据集的某个部分时,它会降低性能。

答案 2 :(得分:1)

根据您解释查询的输出,这是我最初的想法:

您的查询的这一部分(重写以排除不需要的括号):

    p.property_published = 1
    AND p.property_property_type_id = '1' 
    AND p.property_property_type_sale_id = '1'
    AND p.property_property_housing_id = '1' 

property表上放置条件这么多条件,你不可能使用任何索引。除非你有一个索引,其中包含所有这四个属性,否则你要强制对查询进行全表扫描,只是为了找到符合这些条件的行(但是,如果你有一个索引就可以它可以使用的那些属性。)

首先,我添加以下索引(尚未检查此语法错误):

CREATE INDEX property_published_type_sale_housing_idx  
ON property (property_published, 
             property_property_type_id, 
             property_property_type_sale_id, 
             property_property_housing_id );

然后我会重新运行你的EXPLAIN以查看你现在是否点击了索引。 (取消查询部分的FORCE INDEX)。

此外,即使遇到此问题,减速也可能与内存相关。也就是说,您可能有足够的内存来处理具有较少行数的表,但可能是当表变大时,MySQL无法处理内存中的整个查询并被迫开始使用磁盘来获取整个行查询已处理。这可以解释为什么性能会突然下降。

如果是这种情况,那么有两件事可能会有所帮助:

  1. 添加更多内存(并调整mysql配置文件以利用它),以便一次可以处理的行数更大。这至多是一个临时解决方案。

  2. 调整索引(就像我上面说的那样),以便mysql需要处理的行数较少。如果选择要处理的行可以更精确。

答案 3 :(得分:0)

除了一个好的计划,你需要有足够的资源来运行查询。

检查配置中的缓冲区大小和其他关键参数。

您的查询是?