2012-12-18 67 views
0

我正在尋找方法來優化以下SQL查詢。我正在使用MS SQL Server 2008.我想如果有任何方法來整合外部連接,它會加快速度......如果任何人有任何輸入,它將不勝感激。謝謝查詢中使用多個外連接的查詢優化

SELECT employee.employee_id, 
    coalesce (room.ship_id, ship.ship_id) AS ship_id, 
    SUBSTRING (employee.service_id, 0, 6) AS cost_code, 
    employee_station.room_cat AS nws_room_cat 
FROM employee 
    LEFT OUTER JOIN room 
     ON  employee.ship_id = room.ship_id 
     AND employee.floor_id = room.floor_id 
     AND employee.room_id = room.room_id 
    LEFT OUTER JOIN ship 
     ON employee.ship_id = ship.ship_id 
    LEFT OUTER JOIN employee_station 
     ON COALESCE (ship.property_type, '') = 
      COALESCE (employee_station.property_type, '') 
     AND COALESCE (room.work_center_id, '') = COALESCE (employee_station.work_center_id, '') 
     AND COALESCE (employee.pay_plan, '') = 
       COALESCE (employee_station.pay_plan, '') 
     AND COALESCE (employee.employee_type, '') = 
       COALESCE (employee_station.employee_type, '') 
     AND COALESCE (SUBSTRING (employee.service_id, 0, 6), '') = 
       COALESCE (employee_station.cost_code, '') 
    LEFT OUTER JOIN roomtype 
     ON room.room_type = roomtype.room_type 
    LEFT OUTER JOIN dp 
     ON employee.service_id = dp.service_id 

注意:爲了清晰起見,我特意在這裏省略了SELECT語句中的很多字段。因此,roomtype和dp表格實際上正在使用...

+1

爲什麼LEFT JOIN的對錶'roomtype'和'dp'?他們在這裏沒有做任何事情。 – BellevueBob

+0

@BobDuell:很好,我正想問同樣的問題。 – Kaf

+0

哦,實際上有更多的字段是SELECT的一部分..不過我爲了清晰的目的而將它們排除在外......只是使它更簡潔。所以這些表格實際上是需要的,因爲數據正在被他們從中拉出......我只是沒有在這裏包括實際的字段。 – dido

回答

1

OUTER JOINs不是問題。問題在於包裝函數內的列。

ON COALESCE (ship.property_type, '') = COALESCE (employee_station.property_type, '') 

這類建築的阻止優化們進行有效的查詢計劃 - 它不知道該函數的值是什麼,直到運行時間,因此它無法使用,他們應該存在索引。

重寫沒有函數的查詢,優化器將能夠做出更好的決策。

+0

你如何建議我重寫沒有COALESCE函數的查詢?我想我會得到非常不同的結果,如果我刪除這些功能... – dido

+0

問題是,你爲什麼認爲他們是必要的?我自己並不使用sql-server,但是您要加入的表格實際上是否有值表示爲''的行? – BellevueBob

+1

@dido'ON ship.property_type = employee_station.property_type OR(ship.property_type IS NULL AND employee_station.property_type IS NULL)'或'ON EXISTS(SELECT employee_station.property_type INTERSECT SELECT ship.property_type)'see [Untocumented Query Plans:Equality比較](http://sqlblog.com/blogs/paul_white/archive/2011/06/22/undocumented-query-plans-equality-comparisons.aspx) –

0

你可以嘗試加入的校驗 - 從我的經驗,往往給人較複雜條件更好的性能:

SELECT 
--columns you need 
FROM employee 
LEFT OUTER JOIN room 
ON CHECKSUM(employee.ship_id, employee.floor_id, employee.room_id) 
= CHECKSUM(room.ship_id, room.floor_id, room.room_id) 
LEFT OUTER JOIN ship 
ON employee.ship_id = ship.ship_id 
LEFT OUTER JOIN employee_station 
ON CHECKSUM(ship.property_type, room.work_center_id, employee.pay_plan, employee.employee_type, SUBSTRING (employee.service_id, 0, 6)) 
= CHECKSUM(employee_station.property_type, employee_station.work_center_id, employee_station.pay_plan, employee_station.employee_type, employee_station.cost_code) 
LEFT OUTER JOIN roomtype 
ON room.room_type = roomtype.room_type 
LEFT OUTER JOIN dp 
ON employee.service_id = dp.service_id 
+0

的查詢成本(相對於批處理)時,查詢似乎運行速度較慢......最後但並非最不重要:爲什麼room或employee_station表沒有employee_id參考? - 它會讓你的查詢變得更簡單更快 – pkmiec

+0

除了這個已被棄用的事實之外,它也無法工作。[「SET ANSI_NULLS ON只有在比較操作數的其中一個是NULL變量或NULL時纔會影響比較結果。如果比較的兩邊都是列或複合表達式,則該設置不會影響比較。」 ](http://msdn.microsoft.com/en-us/library/ms188048.aspx) –

+0

哦..好點,我會編輯 – pkmiec