3

怎么可能在 EXPLAIN 中有一个好的计划,如下所示并且查询速度很慢。几行,使用索引,没有文件排序。

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

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

建议吗?

解释

查询(1. 可以根据用户选择启用注释字段。2. 没有 FORCE INDEX 我得到了 14 秒。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

查询配置文件

查询配置文件

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

谢谢大家,

阿曼多·米亚尼

4

4 回答 4

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子句来证明这一点。您会看到 MySQL 现在不会使用任何索引,即使是您强制使用的索引(因为索引不适用于此目的)。

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

于 2012-05-16T14:55:52.677 回答
1

有一段时间,您的查询将围绕可能不再适用于给定需求的模型进行优化。

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

您必须分析的是您的索引的确定性。例如,如果“人”表中有“姓名、姓氏”的索引,则如果每个人的姓名和姓氏都相同,则性能会很差。当索引不足以描述数据集的某个部分时,它是一个真正的陷阱。

于 2012-05-16T14:23:42.880 回答
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 需要处理的行数更少。如果它可以更精确地选择它选择进行处理的行。

于 2012-05-16T15:46:13.850 回答
0

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

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

你的查询是?

于 2012-05-16T14:19:17.487 回答