[英]SQL Query on table with 30mill records
我在本地SQL Server中構建表時遇到問題。 原則上它導致tempdb表變滿並拋出異常。 這有很多連接和外部應用,所以要找到問題的具體位置,我在sql查詢的第一個表上做了一個選擇,以確定它花了多長時間,這很快,所以我然后添加了下一個表是第一次加入查詢和重新加入,我繼續這樣做,直到我發現桌子停滯不前。
我發現問題(或至少第一個問題)與shipper_container表有關。 這個表非常龐大,只需單獨獲取一個System.OutOfMemoryException就可以單獨顯示該表的結果(它只有5列)。 它減少了1600萬條記錄,但有3000萬行。 它的大小為1.2GB。 這對我來說似乎沒那么大,SQL Management studio無法處理它。
使用WHERE語句在2015年1月1日至1月10日之間收集值仍然導致搜索超過5分鍾,並且在我取消時仍在執行。 我還在每個選擇參數上添加了索引,這也沒有提高性能。
這是SQL查詢。 你可以看到我已經注釋掉了尚未在其他連接和外部應用中添加的其他參數。
DECLARE @startDate DATETIME
DECLARE @endDate DATETIME
DECLARE @Shipper_Key INT = NULL
DECLARE @Part_Key INT = NULL
SET @startDate = '2015-01-01'
SET @endDate = '2015-01-10'
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
INSERT Shipped_Container
(
Ship_Date,
Invoice_Quantity,
Shipper_No,
Serial_No,
Truck_Key,
Shipper_Key
)
SELECT
S.Ship_Date,
SC.Quantity,
S.Shipper_No,
SC.Serial_No,
S.Truck_Key,
S.Shipper_Key
FROM Shipper AS S
JOIN Shipper_Line AS SL
--ON SL.PCN = S.PCN
ON SL.Shipper_Key = S.Shipper_Key
JOIN Shipper_Container AS SC
--ON SC.PCN = SL.PCN
ON SC.Shipper_Line_Key = SL.Shipper_Line_Key
WHERE S.Ship_Date >= @startDate AND S.Ship_Date <= @endDate
AND S.Shipper_Key = ISNULL(@Shipper_Key, S.Shipper_Key)
AND SL.Part_Key = ISNULL(@Part_Key, SL.Part_Key)
服務器實例在本地網絡上運行 - 這可能是個問題嗎? 我真的很少有這方面的經驗,並且非常感謝幫助,並盡可能詳細和清晰。 通常在SQL論壇中,人們會直接進入我不遵循的技術細節。
不要 Select ... From yourtable
SS Management Studio中的Select ... From yourtable
返回數千或數百萬行的Select ... From yourtable
。 當系統必須在Management Studio數據表中繪制並顯示在屏幕上時,1GB的數據會變得更大
服務器實例在本地網絡上運行
當您執行Select ... From yourtable
SSMS中的Select ... From yourtable
時,服務器必須將所有數據發送到您的筆記本電腦/台式機。 這在網絡上是非常不可取的壓力。 插入時不應該出現問題,因為一切都停留在服務器上。 但是,如果您的數據模型不夠好,保留在服務器上並不意味着它會很快。
設置交易隔離級別無法閱讀;
你使用它可能會得到臟數據......除非你知道它為什么存在以及為什么需要它,否則最好將它刪除。
我還在每個選擇參數上添加了索引,這也沒有提高性能
如果你的意思是索引:
他們的定義是什么? 如果它們是1列上的單個索引,則可以刪除SC.Quantity,S.Shipper_No,SC.Serial_No和S.Truck_Key上的索引。 他們沒有被使用。 Ship_Date和Shipper_key可能很有用。 這一切都取決於您的型號和現有的主鍵。 (您需要描述,見下文)
如果您能告訴我們,它將有助於給出更准確的答案:
如果沒有任何索引有用或者缺少它們,它很可能會讀取整個3個表並嘗試匹配它們。 因為它很大,它沒有足夠的內存來處理它,它使用tempdb來存儲中間數據。
現在我假設shipper_key + PCN是每個表的主鍵。 我想你可以嘗試:
您可以在S.Ship_Date上創建索引
Create Index Shipper_Line_Ship_Date(Ship_Date) -- subject to updates according to your Primary Key
查詢優化器可能不會使用這樣的where子句的索引(如果它們存在):
AND S.Shipper_Key = ISNULL(@Shipper_Key, S.Shipper_Key) AND SL.Part_Key = ISNULL(@Part_Key, SL.Part_Key)
您可以使用:
AND (S.Shipper_Key = @Shipper_Key or @Shipper_Key is null) AND (SL.Part_Key = @Part_Key or @Part_Keyis null)
在Shipper_Key和PCN上有索引會很有幫助
最后
正如我上面所說,我們需要更多地了解您的數據模型(創建表...),主鍵和索引(創建索引)。 你可以在http://sqlfiddle.com/創建一個帶有所有3個創建表及其索引的模型。 然后轉到鏈接並在此處添加鏈接。
在SSMS中,您可以右鍵單擊表並轉到Script Table as / Create To / New Query Window
並在此處或在http://sqlfiddle.com/中添加。 只保留CREATE TABLE ...
部分到第一個GO
。 然后,您可以對所有索引執行相同的操作。
您還應該添加查詢計划的副本。 在SSMS中,轉到Query menu / Display Estimated Execution Plan
然后右鍵單擊將其保存為xml(xml更好)。 它只是一個估計,它不會執行整個查詢。 它應該很快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.