【发布时间】:2015-03-15 21:04:31
【问题描述】:
我正在尝试优化此查询,它从 building_rent_prices 和 building_weather 返回多行,然后对它们进行分组并计算其字段的平均值。到目前为止,这些表都在一百万行以下,但需要几秒钟,有谁知道我如何从复合索引或重写查询中优化它?我假设它应该能够是 100 毫秒或更快的查询,但到目前为止它似乎不能
SELECT b.*
, AVG(r.rent)
, AVG(w.high_temp)
FROM buildings b
LEFT
JOIN building_rent_prices r
ON r.building_id = b.building_id
LEFT
JOIN building_weather w
ON w.building_id = b.building_id
WHERE w.date BETWEEN CURDATE() AND CURDATE + INTERVAL 4 DAY
AND r.date BETWEEN CURDATE() AND CURDATE + INTERVAL 10 day
GROUP
BY b.building_id
ORDER
BY AVG(r.rent) / b.square_feet DESC
LIMIT 10;
解释如下:
1 SIMPLE building_rent_prices 范围
1 个简单的建筑物 eq_ref
1 个简单的建筑_天气参考
在哪里使用;使用索引;使用临时的;使用文件排序
在哪里使用
在哪里使用;使用索引
我正在处理一些测试数据,这里是创建表
CREATE TABLE building(
building_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
square_feet INT
);
CREATE TABLE building_weather(
building_weather_id INT PRIMARY KEY AUTO_INCREMENT,
building_id INT,
weather_date DATE,
high_temp INT
);
CREATE TABLE building_rates(
building_rate_id INT PRIMARY KEY AUTO_INCREMENT,
building_id INT,
weather_date DATE,
rate double
);
ALTER TABLE building_rates INDEX(building_id);
ALTER TABLE buildings INDEX(building_id);
ALTER TABLE building_weather INDEX(building_id);
根据 DRapp 没有索引的回答,这似乎在 1 秒内工作(我仍然需要测试它是否有效)
select
B.*,
BRP.avgRent,
BW.avgTemp
from
( select building_id,
AVG( rent ) avgRent
from
building_rent_prices
where
date BETWEEN CURDATE() AND CURDATE() + 10
group by
building_id
order by
building_id ) BRP
JOIN buildings B
on BRP.building_id = B.building_id
left join ( select building_id,
AVG( hi_temp ) avgTemp
from building_weather
where date BETWEEN CURDATE() AND CURDATE() + 10
group by building_id) BW
on BRP.building_id = BW.building_id
GROUP BY BRP.building_id
ORDER BY BRP.avgRent / 1 DESC
LIMIT 10;
【问题讨论】:
-
将
EXPLAIN和SHOW CREATE TABLE用于查询中的每个表。 -
你试过 EXPLAIN 命令了吗?
-
您可以将
left join更改为inner join,因为where子句正在撤消外连接。此外,由于交叉连接效应,您的平均值可能是错误的。 -
谢谢,我切换到内部连接,但到目前为止性能没有变化
-
您至少需要 5.6 才能获得索引子查询的效率。没有它,随着建筑物数量的增加,查询会变得很慢。
标签: mysql database group-by query-optimization