2008-12-03 82 views
13

我正在將巴西股市數據導入到SQL Server數據庫。現在我有一張表格,裏面有來自三種資產的價格信息:股票,期權和遠期。我仍然在2006年的數據,該表有超過50萬條記錄。我有更多12年的數據導入,所以這張表肯定會超過一百萬條記錄。在SQL Server上優化大型表(+ 1M行)的方法是什麼?

現在,我對優化第一種方法是將數據保持到最小尺寸,所以我減少了行大小到平均60個字節,有以下欄目:

 
[Stock] [int] NOT NULL 
[Date] [smalldatetime] NOT NULL 
[Open] [smallmoney] NOT NULL 
[High] [smallmoney] NOT NULL 
[Low] [smallmoney] NOT NULL 
[Close] [smallmoney] NOT NULL 
[Trades] [int] NOT NULL 
[Quantity] [bigint] NOT NULL 
[Volume] [money] NOT NULL 

現在,第二個方法爲了優化是做一個聚集索引。實際上,主索引會自動修復,並使其成爲具有庫存和日期字段的複合索引。這是獨一無二的,我無法在同一天獲得同一只股票的兩個報價數據。

固定的索引確保來自同一個庫存的報價保持在一起,並且可能按日期排列。這第二個信息是真的嗎?

現在有一半的百萬記錄它採取各地200ms的從一個特定的資產選擇報價。我相信這個數字會隨着桌子的增長而變得更高。

現在對於第三種方法,我在考慮將表分成三張表,每個表用於特定市場(股票,期權和遠期)。這可能會將桌面尺寸減少1/3。現在,這種方法會有幫助還是無關緊要?現在桌子有50MB的大小,所以它可以完全放入RAM而不會有太大麻煩。

另一種方法是使用SQL Server的分區功能。我不太瞭解它,但我認爲它通常在表很大時使用,並且可以跨越多個磁盤以減少I/O延遲,對嗎?在這種情況下分區會有幫助嗎?我相信我可以在不同的表格中劃分最新值(最新年份)和最舊值,尋找最新數據的可能性更高,並且使用小分區可能會更快,對嗎?

什麼是其他的好辦法,以儘可能快的速度?表格的主要選擇用途將用於從特定資產中尋找特定範圍的記錄,例如最近3個月的資產X.將會有另一種用法,但這將是最常見的,可以通過超過3k用戶同時進行。

+0

一些SELECT語句和/或查詢計劃會有所幫助.... – 2008-12-03 17:19:55

回答

11
  1. 在100萬條記錄,我不認爲這是一個特別大的表需要不同尋常的優化技術,如分割表最多,非規範化等,但這些決定會來,當你已經嘗試了所有的正常手段這不會影響您使用標準查詢技術的能力。

現在,第二種優化方法是創建一個聚集索引。實際上,主索引會自動修復,並使其成爲具有庫存和日期字段的複合索引。這是獨一無二的,我無法在同一天獲得同一只股票的兩個報價數據。

固定的索引確保來自同一個庫存的報價保持在一起,並且可能按日期排序。這第二個信息是真的嗎?

它在邏輯上是正確的 - 聚集索引定義了磁盤上記錄的邏輯順序,這是你應該關注的。 SQL Server可能會放棄在物理塊中進行排序的開銷,但它的行爲仍然像是一樣,所以它並不重要。在任何情況下,查詢一隻股票可能會讀取1或2頁;並且優化器不會從頁面讀取中的無序數據中獲益。

現在有了50萬條記錄,它需要大約200毫秒才能從特定資產中選擇700個報價。我相信這個數字會隨着桌子的增長而變得更高。

不一定顯着。表大小和查詢速度之間沒有線性關係。通常有更多更重要的考慮因素。我不會在你描述的範圍內擔心它。這是你擔心的原因嗎? 200毫秒對我來說似乎是很棒的,足以讓你達到加載表格的目的,並且你可以開始做現實測試,並且更好地理解真實的性能。

現在對於第三種方法,我在考慮將表分成三張表格,每張表格分別針對特定市場(股票,期權和遠期)。這可能會將桌面尺寸減少1/3。現在,這種方法會有幫助還是無關緊要?現在桌子有50MB的大小,所以它可以完全放入RAM而不會有太大麻煩。

不!這種優化過早可能是不成熟的。

另一種方法是使用SQL Server的分區功能。

相同的評論。您將能夠長期堅持嚴格的邏輯,完全標準化的模式設計。

什麼是其他的好辦法,使其成爲最快的可能?

最好的第一步是對股票進行聚類。插入速度根本無關緊要,直到您查看每秒插入的多條記錄 - 我在這裏看不到任何活動附近的任何地方。這應該讓你接近最大效率,因爲它可以有效地讀取與股票相關的每條記錄,而這似乎是您最常用的指數。任何進一步的優化都需要根據測試來完成。

10

百萬條記錄真的不是那麼大。它聽起來像是要花太長的時間才能搜索 - 是你搜索索引的列嗎?

一如既往,第一個調用端口應該是SQL分析器和查詢計劃評估器。向SQL Server詢問你將如何處理你感興趣的查詢。我相信你甚至可以讓它建議改變,比如額外的索引。

我不會開始進入分區等等 - 就像你說的那樣,它應該在這一刻都很舒適地坐在內存中,所以我懷疑你的問題更可能是一個缺失的索引。

+0

是的,它已被編入索引,但我忘記了一個非常重要的觀點:我仍在插入數據,這可能會影響搜索。我知道這不是那麼大,但它會經常被查詢。 – 2008-12-03 16:39:31

+0

你有沒有分析過它並檢查了查詢計劃? 你是否總是需要能夠查詢最近的數據?如果不是,您可能會發現最好將其插入一些無索引的表格中,然後在安靜時段對插入物進行分批處理。 – 2008-12-03 16:49:45

1

我在一個學區工作,我們必須跟蹤每個學生的出勤率。這就是我們如何賺錢。我的每張學生持有每日考勤記錄的表格目前有3890萬條記錄。我可以很快從這個單獨的學生出席。我們在這個表上保留4個索引(包括主鍵)。我們的聚集索引是學生/日期,它保留了所有學生的記錄。我們在插入這張桌子時遇到了一個問題,那就是插入了一個學生的舊記錄,但這對我們的目的來說是一個有價值的風險。

關於選擇速度,我肯定會利用緩存在你的情況。

3

首先檢查您的執行計劃。確保你的索引正在被使用。我發現了。一百萬條記錄不是很多。爲了給出一些觀點,我們有一個包含3000萬行的庫存表,並且我們的整個查詢加入了大量的表並且進行了大量的計算,可以在200 MS下運行。我們發現在四路proc 64位服務器上,我們可以擁有更多的記錄,所以我們從不打擾分配。

您可以使用SQL Profier查看執行計劃,或者只是從SQL Management Studio或查詢分析器運行查詢。

0

執行計劃顯示它使用聚簇索引相當好,但我忘記了一個非常重要的事實,我仍在插入數據!該插入可能太頻繁地鎖定桌子。有一種方法可以看到這個瓶頸?

執行計劃似乎沒有顯示任何有關鎖問題。

現在這個數據只是歷史數據,當導入過程結束時,插入將停止並且頻繁出現。但是我很快就會有一個更大的實時數據表,這將會受到這個不斷插入問題的影響,並且會比這張表更大。所以任何優化這種情況的方法都是非常受歡迎的。

+0

使用NOLOCK運行您的選擇跳過任何鎖。不是我推薦用於生產,但可以用它來測試鎖定問題。 Profiler也會顯示你的鎖,但它可能是一個理解。 – 2008-12-03 17:03:06

+0

你插入的速度有多快?如果它們被批量存放,則不需要很長時間就可以存入100萬條記錄。如果你一次只做一個,就不會有干擾。 – dkretz 2008-12-14 00:02:34

3

重新評估索引......這是最重要的部分,數據的大小並不重要,它確實但不完全是爲了速度目的。

我的建議是重新建立該表的索引,爲您最需要的列創建一個複合索引。現在你只有幾條記錄可以播放不同的索引,否則一旦你擁有表格中的所有歷史數據,嘗試新事物就會變得非常煩人。

當你這樣做審查你的查詢,使查詢計劃評估你的朋友,並檢查引擎是否使用正確的索引。

我剛剛讀了你最後一篇文章,有一件事我不明白,你在插入數據時正在查詢表嗎?與此同時?。做什麼的?通過插入,你的意思是一個記錄或幾十萬?你如何插入?逐個?

但是這個關鍵還是索引,不要亂用分區和東西......特別是用毫秒記錄,那沒什麼,我有150萬記錄的表,並且返回40k個特定記錄需要引擎大約1500ms ...

+0

現在的插入程序非常鬆散。我不是批量插入,所以我認爲這是主要問題。在選擇時間內閱讀大小的數字是非常好的,但我沒有辦法知道速度與否。 – 2008-12-03 16:58:43

0

另一種解決方案是爲每年創建一個歷史表,並將所有這些表放入歷史數據庫中,填入所有這些表,然後爲它們創建適當的索引。一旦你完成了這一點,你將不必再次碰觸它們。你爲什麼要繼續插入數據?要查詢所有這些表,您只需「聯合所有」它們:p

當前年表應該與此歷史表有很大不同。對於我所瞭解的你打算在旅途中插入記錄?,我會計劃一些不同的事情,比如隨時隨地進行批量插入或類似的事情。當然,這一切取決於你想要做什麼。

這裏的問題似乎在設計中。我會去做一個新的設計。你現在擁有的是我所瞭解的不適合的東西。

+2

在這個大小的數據庫中,非規範化是個不好的建議,反正年份會是錯誤的。 – dkretz 2008-12-14 00:00:46

1

你已經提到你的主鍵是(Stock,Date)上的化合物,並且是聚簇的。這意味着表格按庫存和日期組織。無論何時插入新行,都必須將其插入表格的中間,這可能導致其他行被推送到其他頁面(頁面拆分)。

我建議嘗試將主鍵換成(日期,股票),並在股票上添加非聚集索引以便於快速查找特定股票。這將允許插入始終發生在表的末尾(假設您按照日期順序插入),並且不會影響表的其餘部分,並且頁面拆分的可能性較小。

0

實際上,主索引會自動關閉,我將它作爲帶有「庫存」和「日期」字段的複合索引。這是獨一無二的,我無法在同一天獲得同一只股票的兩個報價數據。

固定的索引確保來自同一個庫存的報價保持在一起,並且可能按日期排序。這第二個信息是真的嗎?

SQL Server中的索引始終按索引中的列順序排序。因此,[股票,日期]的指數將首先對股票進行排序,然後對股票進行日期排序。 [日期,股票]上的指數將首先按日期排序,然後按日期排序。

執行查詢時,應始終在WHERE部分包含索引的第一列,否則索引不能有效使用。

對於您的特定問題:如果股票的日期範圍查詢是最常見的用法,那麼在[日期,股票]上執行主鍵,這樣數據將按日期按順序存儲在磁盤上,您應該獲得最快的訪問。根據需要構建其他索引。插入大量新數據後,索引重建/統計更新。

相關問題