我有一个查询:
select *
from `ads_fact`
inner join `dim_make` on `dim_make`.`make_id` = `ads_fact`.`make_id`
inner join `dim_model` on `dim_model`.`model_id` = `ads_fact`.`model_id`
inner join `dim_state` on `dim_state`.`state_id` = `ads_fact`.`state_id`
inner join `dim_source` on `dim_source`.`source_id` = `ads_fact`.`source_id`
inner join `dim_fuel_type` on `dim_fuel_type`.`fuel_type_id` = `ads_fact`.`fuel_type_id`
inner join `dim_body_type` on `dim_body_type`.`body_type_id` = `ads_fact`.`body_type_id`
where 1=1
&& date_time >= DATE_SUB(CURDATE(), INTERVAL 14 DAY)
&& ad_status=0
order by ad_id DESC
limit 20
offset 0
我尝试了一些东西,但它的响应时间仍然超过7秒,任何人都可以帮我优化这个查询。
答案 0 :(得分:0)
你可以做几件事:
SET @threshold_date = DATE_SUB(CURDATE(), INTERVAL 14 DAY);
SELECT ....
.....
WHERE date_time >= @threshold_date
答案 1 :(得分:0)
优化器可能并没有很好地处理这个问题。假设所有过滤器都来自ads_fact
表...首先尝试创建过滤表:
CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS (
SELECT *
FROM `ads_fact`
WHERE 1=1
AND year > 2009
AND date_time >= DATE_SUB(CURDATE(), INTERVAL 14 DAY)
AND ad_status=0
ORDER BY ad_id DESC
LIMIT 20
OFFSET 0
)
然后将其加入其他表:
SELECT *
FROM temp1
INNER JOIN `dim_make` ON `dim_make`.`make_id` = temp1.`make_id`
INNER JOIN `dim_model` ON `dim_model`.`model_id` = temp1.`model_id`
INNER JOIN `dim_state` ON `dim_state`.`state_id` = temp1.`state_id`
INNER JOIN `dim_source` ON `dim_source`.`source_id` = temp1.`source_id`
INNER JOIN `dim_fuel_type` ON `dim_fuel_type`.`fuel_type_id` = temp1.`fuel_type_id`
INNER JOIN `dim_body_type` ON `dim_body_type`.`body_type_id` = temp1.`body_type_id`
基本上,这将保证优化器对尽可能小的记录集进行所有过滤。然后将过滤后的集合连接回其他表。您当前的查询很可能正在完成所有连接,然后过滤,排序和限制(或者以低效的顺序执行操作,因为它无法提出一个好的计划)。
答案 2 :(得分:0)
dim_make
有PRIMARY KEY(make_id)
吗?我们来看SHOW CREATE TABLE dim_make
。
ads_fact
有INDEX(status, date_time)
吗?我们来看SHOW CREATE TABLE ads_fact
。
如果ORDER BY date_time DESC
可以,那么运行速度会快得多(在添加上述索引之后)。
如果您担心date_time
中的重复值,请执行
ORDER BY date_time DESC, ad_id DESC
如果在修复了"分页"的第一个页面后,您发现后续页面太慢,请参阅why pagination via OFFSET can be bad上的文章。
另一个问题......你正在接近"过度规范化":
state
也可以是2字节CHAR(2) CHARACTER SET ascii
,而不是4字节INT
。fuel_type
可以是1字节ENUM('unk', 'gas', 'diesel', 'electric', 'hybrid', 'natural gas', 'hydrogen')
,也可以是1字节CHAR(1) CHARACTER SET ascii
,其值类似于' G',' D&#39 ;,' H'等(我不认为JOINs
是您的主要性能问题;我认为索引是。)