[英]Need help improving sql query performance
這是我簡化的歷史記錄表結構:
id | property_id | price | created_at | updated_at | deleted_at
1 | 1 | 100 | 2016-04-10 01:00:00 | 2016-04-10 01:00:00 | NULL
2 | 1 | 300 | 2016-04-10 01:00:00 | 2016-04-10 01:00:00 | NULL
3 | 1 | 300 | 2016-04-10 02:00:00 | 2016-04-10 02:00:00 | NULL
4 | 2 | 200 | 2016-04-10 03:00:00 | 2016-04-10 03:00:00 | NULL
1 | 2 | 150 | 2016-04-10 04:00:00 | 2016-04-10 04:00:00 | NULL
我需要:
到目前為止,這是我的查詢,但是有點慢:
SELECT *
FROM `history` `t1`
WHERE `t1`.`created_at` >= '2016-04-13 00:00:00'
AND `t1`.`created_reason` = 'Scraped'
AND `t1`.`price` > -1
AND (SELECT `t2`.`price`
FROM `history` `t2`
WHERE `t2`.`property_id` = `t1`.`property_id`
AND `t2`.`created_at` < `t1`.`created_at`
AND `t2`.`price` > -1
ORDER BY DATE(`t2`.`created_at`) DESC
LIMIT 1
) <> `t1`.`price`
GROUP BY `t1`.`property_ad_id`
關於如何提高性能的任何建議?
這里有一些建議。
使用EXPLAIN獲取查詢執行計划。
從t1返回的每一行都將執行相關子查詢。 這會大大降低性能。
相關的子查詢對一個函數的結果執行ORDER BY,這意味着MySQL必須對滿足謂詞的每一行都評估該表達式,然后進行排序操作。 (使用LIMIT 1,MySQL可能不必完全對整個集合進行排序,但是它確實需要至少進行一次傳遞才能獲得第一行。)
因為DATE()函數停止了時間成分,所以如果t2中有多行滿足其他謂詞(早期created_at),同一最新日期和不同時間,則不確定將首先對那些行進行排序。 您可能會從04:00開始行而不是從17:00開始行
建議:引用裸露的列,並確保適當的索引可用。
建議:獲取在創建的“最大值”(有效利用索引)
建議:在一周的48小時,72小時內,將您要在t2中查找的前一行的下限設置為下限?
建議:確保適合於t1上的外部查詢和t2上的子查詢的索引。 (可能那些將需要兩個不同的索引)
作為改進的第一步,需要進行一些小調整。
SELECT t1.*
FROM history t1
WHERE t1.created_at >= '2016-04-13 00:00:00'
AND t1.created_reason = 'Scraped'
AND t1.price > -1
AND t1.price <>
(
SELECT t2.price
FROM history t2
WHERE t2.property_id = t1.property_id
AND t2.created_at < t1.created_at
AND t2.created_at > t1.created_at + INTERVAL -30 DAY
AND t2.price > -1
ORDER BY t2.created_at DESC
LIMIT 1
)
GROUP BY t1.property_ad_id
最合適的指標可能是
... ON history(created_reason,created_at,property_id,price)
... ON history(property_id,created_at,price)
為了優化GROUP BY(避免進行排序操作),我們還可以考慮嘗試使用帶有property_ad_id
前導列的索引。 這是一個很長的路,但可能值得一試,以了解EXPLAIN是否顯示它正在使用...
... ON history(property_ad_id,created_reason,created_at,property_id,price)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.