好吧,所以我有一個真正怪異的MySQL表(900K記錄,總共180 MB),並且我想從子組記錄中提取更高的date_updated
並計算加權平均每組。計算運行約15小時,我有一個強烈的感覺,我做錯了。SQL魔術 - 查詢不應該花費15小時,但它確實
首先,滔天表格佈局:
category
element_id
date_updated
value
weight
source_prefix
source_name
只有在這裏關鍵是element_id
(BTREE,8K〜獨特的元素)。
和計算過程:
製作哈希爲每個組和子組。
CREATE TEMPORARY TABLE `temp1` (INDEX (`ds_hash`))
SELECT `category`,
`element_id`,
`source_prefix`,
`source_name`,
`date_updated`,
`value`,
`weight`,
MD5(CONCAT(`category`, `element_id`, `source_prefix`, `source_name`)) AS `subcat_hash`,
MD5(CONCAT(`category`, `element_id`, `date_updated`)) AS `cat_hash`
FROM `bigbigtable` WHERE `date_updated` <= '2009-04-28'
我真的不明白這一點做文章用哈希,但它的工作速度更快這種方式。黑暗魔法,我推測。
查找最大日期爲每個小組
CREATE TEMPORARY TABLE `temp2` (INDEX (`subcat_hash`))
SELECT MAX(`date_updated`) AS `maxdate` , `subcat_hash`
FROM `temp1`
GROUP BY `subcat_hash`;
加入與TEMP2 temp1中找到的加權平均值爲類別
CREATE TEMPORARY TABLE `valuebycats` (INDEX (`category`))
SELECT `temp1`.`element_id`,
`temp1`.`category`,
`temp1`.`source_prefix`,
`temp1`.`source_name`,
`temp1`.`date_updated`,
AVG(`temp1`.`value`) AS `avg_value`,
SUM(`temp1`.`value` * `temp1`.`weight`)/SUM(`weight`) AS `rating`
FROM `temp1` LEFT JOIN `temp2` ON `temp1`.`subcat_hash` = `temp2`.`subcat_hash`
WHERE `temp2`.`subcat_hash` = `temp1`.`subcat_hash`
AND `temp1`.`date_updated` = `temp2`.`maxdate`
GROUP BY `temp1`.`cat_hash`;
(現在,我通過它看上去並寫了這一切在我看來,我應該在最後一個查詢中使用INNER JOIN(避免900k * 900k臨時表))。
還是,有沒有正常的方式這樣做?
UPD:一些圖像以供參考:
除去死ImageShack的鏈路
UPD:解釋提出的解決方案:
+----+-------------+-------+------+---------------+------------+---------+--------------------------------------------------------------------------------------+--------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------+---------------+------------+---------+--------------------------------------------------------------------------------------+--------+----------+----------------------------------------------+
| 1 | SIMPLE | cur | ALL | NULL | NULL | NULL | NULL | 893085 | 100.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | next | ref | prefix | prefix | 1074 | bigbigtable.cur.source_prefix,bigbigtable.cur.source_name,bigbigtable.cur.element_id | 1 | 100.00 | Using where |
+----+-------------+-------+------+---------------+------------+---------+--------------------------------------------------------------------------------------+--------+----------+----------------------------------------------+
最後一個。首先是瞬間,第二是約23分鐘。 – 2009-05-22 10:23:08
我可以刪除哈希,但然後查詢將需要無限的時間(好吧,也許不是,但我沒有這樣的耐心,也沒有客戶端)。我想這些散列可以以某種方式被製作成索引。 – 2009-05-22 10:25:43