提高 MySQL 查询性能 - 可能的索引问题
Posted
技术标签:
【中文标题】提高 MySQL 查询性能 - 可能的索引问题【英文标题】:Improving MySQL query performance - possible index problems 【发布时间】:2015-02-09 10:47:25 【问题描述】:我见过很多类似我的问题,但在阅读完所有问题后,我感到很困惑。
总而言之 - 我有一个查询,它从表中选择产品并从其他表中添加有关它们的更多信息。
查询:
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
我认为问题在于表的索引。你能告诉我如何设置它们吗?
如果您需要有关表格或其他任何信息的更多信息,请告诉我!
最好, 迪米塔
【问题讨论】:
你知道 "WHERE (pcr.ctg_id = '19')" 使 pcr 外连接作为内连接执行吗? (如果您真的想要左连接,请将条件移动到左连接的 ON 子句。) 你在ASC LIMIT 1) image_filelocation,
附近漏了一个逗号括号内的查询结束后应该有一个逗号
这两者之间应该有“as”。
如果在没有最后一个LIMIT
的情况下运行,查询预计返回多少行?在这里,指令ORDER BY DESC LIMIT
只能在整个工作完成后进行评估。我猜有些 ctg_id/man_id 部分相当大。
@user4419802 - 大约 1000 个结果。
【参考方案1】:
如果您的“ID”列实际上是数字,请删除它们周围的暗示字符串的引号......即使它会隐含转换。如果是数字,请保持数字。
正如 cmets 中的另一个所说,您通过“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”添加一个新列来对产品表进行去规范化。然后,向您的 Gallery 表添加一个触发器,任何插入或更新都会将第一个“showOrder”值推回产品表。这样,当您查询时,您只需在产品上的该表中添加另一个联接并知道显示订单。如果您的画廊返回 1000 条记录,即使您只限制为 24 条,它仍然需要在应用 order by 之前获取所有记录。因此,每个图库图像都有 1000 个子查询。
你的字段选择会变成
gal.image_filelocation,
您的 JOIN 将添加以下内容
LEFT JOIN 3w_products_gallery gal
on p.product_id = gal.product_id
AND p.GalleryShowOrder = gal.show_order
【讨论】:
'table 3w_products_gallery 应该有一个索引 ON (product_id, show_order)' - 好吧,它只有在给定 id 有一堆图像时才有用。否则,纯index ON (product_id)
就足够了。
'main 3w_products table 应该在 (man_id, product_id )' 上有一个索引 - 同样,如果 TS 声明查询返回不超过 1000 行,则使用复合优化 ORDER BY
是没有用的指数。另请考虑,mysql 可能无法优化ORDER BY DESC
,因为它需要不支持的index ON (man_id, product_id DESC)
(请参阅use-the-index-luke.com/sql/sorting-grouping/…)以上是关于提高 MySQL 查询性能 - 可能的索引问题的主要内容,如果未能解决你的问题,请参考以下文章