提高MySQL查询性能 - 可能的索引问题

时间:2015-02-09 10:47:25

标签: php mysql sql performance

我看过像我这样的很多问题,但在读完这些问题后,我感到非常困惑。

总结一下 - 我有一个查询从表中选择产品,并从其他表中添加有关它们的更多信息。

查询:

SELECT 
      p.product_id, 
      p.product_name, 
      p.product_seo_url, 
      p.product_second_name, 
      p.product_intro_plain, 
      p.product_price,
      p.product_price_promo, 
      p.product_promo_expire_date, 
      p.product_views,
      p.product_code, 
      p.product_exquisite, 
      p.product_rating, 
      p.product_votes,
      p.product_date_added, 
      p.product_returned, 
      p.product_price_returned,
      ( SELECT gal.image_filelocation 
           FROM 3w_products_gallery gal 
           WHERE gal.product_id = p.product_id 
           ORDER BY show_order ASC 
           LIMIT 1 )  image_filelocation, 
      m.man_image_location, 
      m.man_name, 
      m.man_seo_url 
   FROM 
      3w_products p 
         LEFT JOIN 3w_manufacturers m 
            ON p.man_id = m.man_id
         LEFT JOIN 3w_products_cat_rel pcr 
            ON p.product_id  = pcr.product_id
   WHERE 
          pcr.ctg_id = '19'
      AND p.man_id = '190'
   ORDER BY 
      p.product_id DESC 
   LIMIT 
      0, 24

发生的奇怪事情是查询有时会执行0.001秒。有时候超过30秒。

EXPLAIN显示: http://i.stack.imgur.com/ZNtBX.png

我认为问题在于表的索引。你能告诉我如何设置它们吗?

如果您需要有关表格或其他任何信息,请告诉我们。

最佳, 迪米塔尔

1 个答案:

答案 0 :(得分:0)

如果您的“ID”列实际上是数字,请删除它们周围的引号,这意味着字符串......即使它会隐含转换。如果是数字,请保持数字。

正如评论中的另一篇所述,您的LEFT JOIN通过“pcr”别名及其WHERE子句中的条件将其转换为内部联接。

 FROM 
      3w_products p 
         LEFT JOIN 3w_manufacturers m 
            ON p.man_id = m.man_id
         LEFT JOIN 3w_products_cat_rel pcr 
            ON p.product_id  = pcr.product_id
            AND pcr.ctg_id = 19
   WHERE 
      AND p.man_id = 190

字段级查询可能会导致性能下降,因为每个字段的选择(图像位置)对每个记录都执行一次。为了至少帮助这个性能,表3w_products_gallery应该有一个索引ON(product_id,show_order)

您的主要3w_products表应该有一个索引(man_id,product_id)... Man_ID用于按制造商优化WHERE子句,还有产品ID以帮助优化ORDER BY标准。

你的3w_manufacturers表,我怀疑在(man_id)上已经有一个有效的索引,因为它似乎是该表的主键。

此外,作为基于网络的内容,您可能最好通过为“GalleryShowOrder”添加一个新列来对您的产品表进行DE-NORMALIZE。然后,向Gallery表添加一个触发器,任何插入或更新都会将第一个“showOrder”值推回到product表中。这样,当您查询时,您只需在产品和已知显示顺序上向该表添加另一个连接。如果您的图库返回1000条记录,即使您只限制为24条记录,它仍然需要在应用订单之前获取所有记录。因此每个图库图像的1000个子查询。

您的字段选择将变为

gal.image_filelocation, 

你的JOIN会添加以下内容

  LEFT JOIN 3w_products_gallery gal 
     on p.product_id = gal.product_id
    AND p.GalleryShowOrder = gal.show_order