我的 SQL 查询这么慢正常吗?
Posted
技术标签:
【中文标题】我的 SQL 查询这么慢正常吗?【英文标题】:Is it normal for my SQL Query to be this slow? 【发布时间】:2013-01-16 18:27:07 【问题描述】:我遇到了系统过载的问题。 下面的查询是从 3 个表中获取数据,其中 2 个表的记录超过 10.000 条,运行时间为 50 秒。
SELECT DISTINCT
p.prod_name,
p.prod_price,
Sum(dt.vt_qtd) as total_qtd
FROM tdb_products p
LEFT JOIN tdb_sales_temp dt ON p.prod_mp_id = dt.vt_product
LEFT JOIN tdb_sales s ON dt.vt_cupom = s.sl_coupom
WHERE
s.sl_day = $day_link AND
s.sl_mon = $mon_link AND
s.sl_year = $year_link
GROUP BY
p.prod_name
ORDER BY
p.prod_name ASC
这正常吗?
已解决!
【问题讨论】:
你有什么索引? 我注意到您在 WHERE 子句中使用了单独的日、月和年列。如果将它们组合为带有索引的单个DATE
列,则可能会产生很大影响(加上所有 DATE 函数的好处)
使用GROUP BY
,是否需要DISTINCT
?
@halfter:因为数据库很乐意接受 prod_name 分组并同时选择 prod_name 和 prod_price,所以它可能是 mysql。
@halfer: ungrouped prod_price
在SELECT
列表中我认为几乎可以解释它
【参考方案1】:
SELECT prod_name, prod_price, SUM(dt.vt_qtd) AS total_qtd
FROM tdb_sales s
JOIN tdb_sales_temp dt
ON dt.vt_cupom = s.sl_coupom
JOIN tdb_products p
ON p.prod_mp_id = dt.vt_product
WHERE (s.sl_day, s.sl_mon, s_sl_year) = ($day_link, $mon_link, $year_link)
GROUP BY
p.prod_name -- but it's better to group by product's PRIMARY KEY
删除DISTINCT
(这是多余的,因为你有GROUP BY
并选择分组字段)
将LEFT JOIN
重写为INNER JOIN
,因为您在LEFT JOIN
'ed 表上有过滤条件。
创建索引:
tdb_sales (sl_year, sl_mon, sl_day, sl_coupom)
tdb_sales_temp (vt_cupom, vt_product)
tdp_product (prod_mp_id) -- it's probably a PRIMARY KEY and you already have it
【讨论】:
天啊!!我创建了索引,响应时间降至 1 秒。谢谢!!!! 为什么创建一个简单的索引会减少时间?有限制吗?再次感谢! @evdutcos:因为这就是索引的用途,提高性能。您是否也重写了查询? @evdutcos 是的,创建索引有一个限制:服务器必须维护索引,因此它会使单独的插入/更新/删除查询慢一点……但你可以看,仔细使用索引,选择方面的改进是显着的。【参考方案2】:简短的回答是否定的,这绝对不是一个合适的时间长度。任何常见的数据库系统都应该能够以亚秒级的时间处理多个 10,000 行表。
不知道完整的架构或 dbms 后端,我的建议是:
索引 - 确保连接中使用的列有正确的索引 数据类型 - 如果要连接的列的数据类型不同,则 dbms 必须为每个行连接执行转换,这可能会导致显着的性能消耗。
【讨论】:
以上是关于我的 SQL 查询这么慢正常吗?的主要内容,如果未能解决你的问题,请参考以下文章