2009-11-15 17 views
0

我怎麼可以重寫以下查詢返回很少的IO操作,但響應時間結果SQL:優化查詢到有幾個IO操作

select 
    *, 
    (select Product_Name from InventoryMaster J2 where J1.ParentItem=J2.ItemId) as ParentName, 
    (select Description from InventoryMaster J2 where J1.ParentItem=J2.ItemId) as ParentDesc 
from 
    InventoryMaster J1 
where 
    Flag like '%N%' 

的InventoryMaster表有一個父項目列在那裏將存儲其他記錄ItemId(對於親子關係)的某些記錄

+0

如果你給的細節有關的數據庫,以及關於這將有助於多少行的表格中。 – 2009-11-15 09:45:29

+1

也是物理或邏輯IO?它取決於內存大小,數據大小,索引... – 2009-11-15 09:46:52

回答

6
where 
    Flag like '%N%' 

上面的這樣的錯誤使數據庫難以有效回答此查詢。它必須查看「標誌」列的每個值並檢查字符串中的「N」。

這可以更改爲只是Flag = 'N'

如果答案是否定的,那麼數據庫設計不正確。你應該在一列中存儲一個東西,而不是多個。搜索「數據庫規範化」。

您應該考慮將查詢重寫爲三個表之間的聯接,而不是像查詢那樣使用子選擇。

+1

事實上,改爲'N%'將允許使用索引.... – 2009-11-15 13:48:45

2

爲什麼不在孩子和父母之間使用JOIN?就像這樣:

SELECT 
    J1.*, 
    J2.Product_Name AS ParentName, 
    J2.Description AS ParentDesc 
FROM InventoryMaster AS J1 
LEFT JOIN InventoryMaster AS J2 ON J2.ItemId = J1.ParentItem 
WHERE J1.Flag LIKE '%N%' 
4

這可能是數據庫

select 
    J1.*, 
    J2.Product_Name as ParentName, 
    J2.Description as ParentDesc 
from 
    InventoryMaster J1 
left join InventoryMaster J2 on J1. ParentItem = J2.ItemID 
where 
    Flag like '%N%' 

上輕了一點,但大殺手仍然是類似的條款。建議你重做那個存儲N標誌的單個字段。

0

另外,不要使用SELECT *。您可能正在回收未使用的列 - 或者某人可能在未來添加大量的TEXT列,而您的應用程序不會期望/使用這些列,這將進一步降低查詢的性能。

我認爲使用JOIN進行更改對於改善性能與LIKE'%N%'問題同樣重要 - 在您的原始語法中,SQL必須進行大量關聯查詢才能獲得父Product_Name和Description (除非優化器足夠聰明以發現...)

實際上,LIKE問題可能是靜音的 - 即使Flag列被索引,我也無法看到使用它的SQL [用於EQUALS測試]只有值是Y和N,並且是均勻分佈的(如果Flag = N是行中非常小的比例[即高度選擇性],那麼優化器可以使用索引[通過檢查統計索引])。因此,如果SQL必須執行全表掃描來解決Flag ='N',那麼它不需要做更多的工作。標記LIKE'%N%'

然後,通過在ParentItem上有一個索引而另一對項目ID(可能是反正你的主鍵)

(我的知識僅與MS SQL Server)的