2011-06-27 106 views
1

我通常在java中完成大部分工作,但我無法真正找到我在這裏做的事情,導致它需要複製到表中並死亡。避免複製到臨時表

SELECT company.tblusers.userid, 
db.operations.id AS operation_id, 
SUM(TIME_TO_SEC(db.batch_log.time_elapsed)) AS time_elapsed, 
SUM(db.tasks.estimated_nonrecurring + db.tasks.estimated_recurring) AS total_elapsed, 
COUNT(db2.ncr_ncr.id) AS number_of_ncrs 
FROM company.tblusers 
INNER JOIN db.operations 
INNER JOIN db.batch_log ON company.tblusers.userid = batch_log.userid 
INNER JOIN db.batches ON batch_log.batch_id = batches.id 
INNER JOIN db.tasks ON db.batches.id = db.tasks.batch_id 
INNER JOIN db2.ncr_ncr ON company.tblusers.sugar_name = db2.ncr_ncr.employee 
WHERE company.tblusers.departmentid = 8 
AND db.operations.id = db.batches.operation_id 
AND db.batches.id = db.tasks.batch_id 
AND db.batch_log.userid = company.tblusers.userid 
AND db2.ncr_ncr.employee = company.tblusers.sugar_name 
GROUP by company.tblusers.userid, db.batches.operation_id 

編輯:Explain輸出

"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra" 
"1";"SIMPLE";"ncr_ncr";"ALL";NULL;NULL;NULL;NULL;"2700";"Using temporary; Using filesort" 
"1";"SIMPLE";"batch_log";"ALL";NULL;NULL;NULL;NULL;"78026";"" 
"1";"SIMPLE";"tblusers";"eq_ref";"PRIMARY";"PRIMARY";"52";"ramses.batch_log.userid";"1";"Using where" 
"1";"SIMPLE";"tasks";"ref";"Index 2";"Index 2";"38";"ramses.batch_log.batch_id";"2";"" 
"1";"SIMPLE";"batches";"eq_ref";"PRIMARY";"PRIMARY";"38";"ramses.tasks.batch_id";"1";"Using where" 
"1";"SIMPLE";"operations";"eq_ref";"PRIMARY";"PRIMARY";"4";"ramses.batches.operation_id";"1";"Using where; Using index" 
+2

臨時表在哪裏? – MPelletier

+0

你爲什麼說這是複製表格?你得到什麼確切的信息? – MPelletier

+0

我運行它,並在它說它正在複製到一個臨時表後顯示在heidisql進程列表中。 – davidahines

回答

8

如果您彙總而分組對列的非索引組合的值,那麼SQL引擎將創建臨時表作爲其正常功能的一部分爲了保持部分彙總的值。您需要爲company.tblusers.useriddb.batches.operation_id的每個組合計算兩個SUM和COUNT。這些值必須存儲,因爲很明顯,沒有包含這兩列的索引,因爲它們在不同的表中。

但是,我不知道它爲什麼會死亡,除非它實際上將完全連接構建爲臨時表,因爲COUNT聚合。

而不是加入到db2.ncr_ncr表中,您應該將其作爲相關的子查詢。這可能需要更少的存儲:

SELECT 
     company.tblusers.userid, 
     db.operations.id AS operation_id, 
     SUM(TIME_TO_SEC(db.batch_log.time_elapsed)) AS time_elapsed, 
     SUM(db.tasks.estimated_nonrecurring + db.tasks.estimated_recurring) AS total_elapsed, 
     (SELECT COUNT(*) FROM db2.ncr_ncr WHERE db2.ncr_ncr.employee = company.tblusers.sugar_name) AS number_of_ncrs 
FROM 
     company.tblusers 
     INNER JOIN db.batch_log ON batch_log.userid = company.tblusers.userid 
     INNER JOIN db.batches ON db.batches.id = db.batch_log.batch_id 
     INNER JOIN db.operations ON db.operations.id = db.batches.operation_id 
     INNER JOIN db.tasks ON db.tasks.batch_id = db.batch_log.batch_id 
WHERE 
     company.tblusers.departmentid = 8 
GROUP BY 
     company.tblusers.userid, 
     db.batches.operation_id 

UPDATE

基礎上解釋計劃的結果,你沒有任何索引查詢可以在ncr_ncr使用。這不好。它實際上創建了一個新的表格副本,它可以按employee排序,以便連接可以在合理的時間內發生。

即使該表格不是很大(只有2700行),您仍然需要在db2.ncr_ncr.employee上放置一個索引(最好是相關的,如果系統的其餘部分允許),否則您的性能將受到嚴重影響。這張表格足夠小,製作和分類臨時副本不應該是一個問題,但它仍然會損害您的表現。

batch_log.userid也是如此。

+0

這一切都是最有幫助的,謝謝你的詳細回覆。 – davidahines

+0

@dah - 不客氣! –

+0

雖然我有點不明白你到達那裏。有沒有一本書或你會推薦閱讀的東西,以便我能更好地理解這一點? – davidahines