2008-12-03 29 views
13

Tôi đang nhập dữ liệu thị trường chứng khoán Braxin vào cơ sở dữ liệu SQL Server. Ngay bây giờ tôi có một bảng với thông tin về giá từ ba loại tài sản: cổ phiếu, lựa chọn và tiền đạo. Tôi vẫn còn trong năm 2006 dữ liệu và bảng có hơn nửa triệu hồ sơ. Tôi có thêm 12 năm dữ liệu để nhập vì vậy bảng sẽ vượt quá một triệu bản ghi chắc chắn.Cách tiếp cận của bạn để tối ưu hóa các bảng lớn (+ 1M hàng) trên SQL Server là gì?

Bây giờ, cách tiếp cận đầu tiên của tôi để tối ưu hóa là để giữ cho dữ liệu đến một kích thước tối thiểu, vì vậy tôi giảm kích thước hàng với mức trung bình của 60 byte, với các cột sau:

 
[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 

Bây giờ, cách tiếp cận thứ hai để tối ưu hóa là tạo chỉ mục nhóm. Trên thực tế, chỉ mục chính được tự động nén và tôi đã biến nó thành một chỉ mục phức hợp với các trường Cổ phiếu và Ngày tháng. Điều này là duy nhất, tôi không thể có hai dữ liệu trích dẫn cho cùng một cổ phiếu trong cùng một ngày.

Chỉ số rỉ sét đảm bảo rằng các dấu ngoặc kép từ cùng một cổ phiếu ở lại với nhau và có thể được sắp xếp theo ngày. Thông tin thứ hai này có đúng không?

Ngay bây giờ với một nửa triệu bản nó lấy khoảng 200ms để chọn trích dẫn từ một tài sản cụ thể. Tôi tin rằng con số này sẽ cao hơn khi bảng phát triển.

Bây giờ với cách tiếp cận thứ ba, tôi nghĩ có thể chia bảng thành ba bảng, mỗi bảng cho một thị trường cụ thể (cổ phiếu, tùy chọn và tiền đạo). Điều này có thể sẽ giảm kích thước bảng xuống 1/3. Bây giờ, cách tiếp cận này sẽ giúp hoặc nó không quan trọng quá nhiều? Ngay bây giờ bảng có kích cỡ 50MB để nó có thể vừa với RAM hoàn toàn mà không gặp nhiều rắc rối.

Một cách tiếp cận khác sẽ sử dụng tính năng phân vùng của SQL Server. Tôi không biết nhiều về nó nhưng tôi nghĩ rằng nó thường được sử dụng khi các bảng lớn và bạn có thể trải rộng trên nhiều đĩa để giảm độ trễ I/O, tôi có đúng không? Việc phân vùng có hữu ích trong trường hợp này không? Tôi tin rằng tôi có thể phân vùng các giá trị mới nhất (năm mới nhất) và giá trị cũ nhất trong các bảng khác nhau, xác suất tìm kiếm dữ liệu mới nhất cao hơn và với phân vùng nhỏ, có thể sẽ nhanh hơn, đúng không?

Cách tiếp cận tốt khác để làm điều này nhanh nhất có thể là gì? Việc sử dụng chủ yếu của bảng sẽ là để tìm kiếm một phạm vi cụ thể của các bản ghi từ một tài sản cụ thể, như 3 tháng mới nhất của tài sản X. Sẽ có một tập quán khác nhưng điều này sẽ là phổ biến nhất, có thể được thực hiện bởi hơn 3k người dùng đồng thời.

+0

Một số câu lệnh SELECT và/hoặc kế hoạch truy vấn sẽ giúp .... –

Trả lời

11
  1. Tại 1 triệu bản ghi, tôi sẽ không coi đây là một bảng đặc biệt lớn cần các kỹ thuật tối ưu hóa bất thường như chia bảng, không chuẩn hóa, v.v ... Nhưng những quyết định đó sẽ đến khi bạn đã thử tất cả các phương tiện thông thường không ảnh hưởng đến khả năng sử dụng các kỹ thuật truy vấn chuẩn của bạn.

Bây giờ, cách tiếp cận thứ hai để tối ưu hóa là tạo chỉ mục nhóm. Trên thực tế, chỉ mục chính được tự động nén và tôi đã biến nó thành một chỉ mục phức hợp với các trường Cổ phiếu và Ngày tháng. Điều này là duy nhất, tôi không thể có hai dữ liệu trích dẫn cho cùng một cổ phiếu trong cùng một ngày.

Chỉ số bị rỉ sét đảm bảo rằng các dấu ngoặc kép từ cùng một cổ phiếu ở lại với nhau và có thể được sắp xếp theo ngày. Thông tin thứ hai này có đúng không?

Đó là sự thật về mặt logic - chỉ mục nhóm xác định thứ tự logic của các bản ghi trên đĩa, đó là tất cả những gì bạn cần quan tâm. SQL Server có thể bỏ qua chi phí phân loại trong một khối vật lý, nhưng nó vẫn sẽ hoạt động như thể nó đã làm, vì vậy nó không đáng kể. Truy vấn một cổ phiếu có thể sẽ là 1 hoặc 2 lần đọc trang trong mọi trường hợp; và trình tối ưu hóa không được hưởng lợi nhiều từ dữ liệu không có thứ tự trong một trang được đọc.

Ngay bây giờ với một nửa triệu bản ghi, khoảng 200ms để chọn 700 trích dẫn từ một nội dung cụ thể. Tôi tin rằng con số này sẽ cao hơn khi bảng phát triển.

Không nhất thiết phải đáng kể. Không có mối quan hệ tuyến tính giữa kích thước bảng và tốc độ truy vấn. Thường có nhiều cân nhắc quan trọng hơn. Tôi sẽ không lo lắng về nó trong phạm vi bạn mô tả. Đó có phải là lý do bạn quan tâm không? 200 ms dường như với tôi là tuyệt vời, đủ để giúp bạn đến mức mà các bảng của bạn được tải và bạn có thể bắt đầu làm thử nghiệm thực tế, và có được một ý tưởng tốt hơn về hiệu suất thực tế cuộc sống.

Bây giờ cho cách tiếp cận thứ ba, tôi nghĩ có thể chia bảng thành ba bảng, mỗi bảng cho một thị trường cụ thể (cổ phiếu, tùy chọn và chuyển tiếp). Điều này có thể sẽ giảm kích thước bảng xuống 1/3. Bây giờ, cách tiếp cận này sẽ giúp hoặc nó không quan trọng quá nhiều? Ngay bây giờ bảng có kích cỡ 50MB để nó có thể vừa với RAM hoàn toàn mà không gặp nhiều rắc rối.

Không! Loại tối ưu hóa này quá sớm nên có lẽ là chết.

Một cách tiếp cận khác sẽ sử dụng tính năng phân vùng của SQL Server.

cùng một nhận xét. Bạn sẽ có thể gắn bó trong một thời gian dài để thiết kế lược đồ hoàn toàn hợp lý, được chuẩn hóa hoàn toàn.

Cách tiếp cận tốt khác để làm điều này nhanh nhất có thể là gì?

Bước đầu tiên tốt nhất là phân nhóm trên cổ phiếu. Tốc độ chèn là không có hậu quả gì cả cho đến khi bạn đang xem nhiều bản ghi được chèn vào mỗi giây - Tôi không thấy bất cứ điều gì ở gần hoạt động đó ở đây. Điều này sẽ giúp bạn đạt hiệu quả tối đa bởi vì nó sẽ đọc hiệu quả mọi bản ghi liên kết với một cổ phiếu và đó có vẻ là chỉ mục phổ biến nhất của bạn. Bất kỳ việc tối ưu hóa nào khác cần được thực hiện dựa trên thử nghiệm.

10

Một triệu bản ghi thực sự không phải là lớn. Có vẻ như quá lâu để tìm kiếm - là cột bạn đang tìm kiếm không được lập chỉ mục?

Như mọi khi, cổng đầu tiên của cuộc gọi phải là trình đánh giá lược đồ và truy vấn SQL. Hỏi SQL Server những gì nó sẽ làm gì với các truy vấn mà bạn quan tâm. Tôi tin rằng bạn thậm chí có thể yêu cầu nó đề xuất các thay đổi như các chỉ mục phụ.

Tôi sẽ không bắt đầu tham gia vào phân vùng, v.v. - như bạn nói, tất cả nên thoải mái ngồi trong bộ nhớ tại thời điểm này, vì vậy tôi nghi ngờ vấn đề của bạn có nhiều khả năng là chỉ mục bị thiếu.

+0

Có, nó được lập chỉ mục nhưng tôi quên một điểm cực kỳ quan trọng: Tôi vẫn chèn dữ liệu, điều đó có thể ảnh hưởng đến tìm kiếm rất nhiều. Tôi biết nó không phải là lớn nhưng nó sẽ được truy vấn rất thường xuyên. –

+0

Và bạn đã lược tả chưa và đã kiểm tra gói truy vấn? Bạn có luôn luôn cần để có thể truy vấn dữ liệu gần đây nhất không? Nếu không, bạn có thể tìm thấy nó tốt nhất để chèn vào một số bảng chưa lập chỉ mục, sau đó ghép hàng loạt các chèn trong thời gian yên tĩnh. –

1

Tôi làm việc cho một khu học chánh và chúng tôi phải theo dõi sự tham dự của từng học sinh. Đó là cách chúng tôi kiếm tiền. Bảng của tôi có dấu chấm công hàng ngày cho mỗi học sinh hiện tại là 38,9 triệu bản lớn. Tôi có thể kéo dài sự tham gia của một học sinh rất nhanh chóng từ điều này. Chúng tôi giữ 4 chỉ mục (bao gồm cả khóa chính) trên bảng này. Chỉ số nhóm của chúng tôi là sinh viên/ngày giữ tất cả hồ sơ của học sinh theo thứ tự đó.Chúng tôi đã có một hit trên chèn vào bảng này liên quan đến điều đó trong trường hợp một kỷ lục cũ cho một sinh viên được chèn vào, nhưng nó là một rủi ro đáng giá cho các mục đích của chúng tôi.

Liên quan đến tốc độ chọn, tôi chắc chắn sẽ tận dụng bộ nhớ đệm trong trường hợp của bạn.

3

Kiểm tra kế hoạch thực hiện của bạn trên truy vấn đó trước. Đảm bảo các chỉ mục của bạn đang được sử dụng. Tôi đã tìm thấy điều đó. Một triệu bản ghi không nhiều. Để cung cấp cho một số quan điểm, chúng tôi đã có một bảng kiểm kê với 30 triệu hàng trong đó và toàn bộ truy vấn của chúng tôi đã tham gia tấn các bảng và đã thực hiện rất nhiều phép tính có thể chạy dưới 200 MS. Chúng tôi thấy rằng trên máy chủ quad proc 64 bit, chúng tôi có thể có nhiều bản ghi đáng kể hơn vì vậy chúng tôi không bao giờ làm phiền việc chia tay.

Bạn có thể sử dụng SQL Profier để xem kế hoạch thực hiện hoặc chỉ chạy truy vấn từ SQL Management Studio hoặc Query Analyzer.

0

Kế hoạch thực hiện cho thấy nó đang sử dụng chỉ số nhóm khá tốt, nhưng tôi đã quên một thực tế cực kỳ quan trọng, tôi vẫn đang chèn dữ liệu! Chèn có lẽ là khóa bảng quá thường xuyên. Có cách nào chúng ta có thể thấy nút cổ chai này?

Kế hoạch thực hiện dường như không hiển thị bất kỳ điều gì về các vấn đề về khóa.

Ngay bây giờ dữ liệu này chỉ là lịch sử, khi quá trình nhập hoàn tất việc chèn sẽ ngừng và ít thường xuyên hơn nhiều. Nhưng tôi sẽ có một bảng lớn hơn cho dữ liệu thời gian thực sớm, điều đó sẽ bị vấn đề chèn hằng số và sẽ lớn hơn bảng này. Vì vậy, bất kỳ phương pháp nào để tối ưu hóa loại tình huống này đều rất được hoan nghênh.

+0

Chạy lựa chọn của bạn với NOLOCK để bỏ qua bất kỳ khóa nào. Không phải là tôi khuyên bạn nên sản xuất, nhưng bạn có thể sử dụng nó để kiểm tra các vấn đề về khóa. Profiler cũng sẽ cho bạn thấy ổ khóa, nhưng nó có thể là một con gấu để phân loại. –

+0

Bạn chèn nhanh như thế nào? Nó sẽ không mất nhiều thời gian để đưa vào 1 triệu hồ sơ nếu chúng được sắp xếp theo lô. Nếu bạn làm từng cái một, sẽ không có sự can thiệp. – dkretz

3

Đánh giá lại các chỉ mục ... đó là phần quan trọng nhất, kích thước của dữ liệu không thực sự quan trọng, nhưng nó cũng không hoàn toàn cho mục đích tốc độ.

Đề xuất của tôi đang xây dựng lại các chỉ mục cho bảng đó, tạo một chỉ mục tổng hợp cho các cột bạn cần nhất. Bây giờ bạn chỉ có một vài bản ghi chơi với các chỉ mục khác nhau nếu không nó sẽ nhận được khá khó chịu để thử những điều mới khi bạn có tất cả các dữ liệu lịch sử trong bảng.

Sau khi bạn làm điều đó xem xét truy vấn của bạn, hãy lập kế hoạch truy vấn đánh giá bạn của bạn và kiểm tra xem động cơ có sử dụng đúng chỉ mục hay không.

Tôi chỉ đọc cho bạn bài đăng cuối cùng, có một điều tôi không nhận được, bạn đang quering bảng trong khi bạn chèn dữ liệu? cùng một lúc?. Để làm gì? bằng cách chèn, bạn có nghĩa là một bản ghi hoặc hàng trăm ngàn? Bạn đang chèn như thế nào? từng cái một? Nhưng một lần nữa chìa khóa của việc này là các chỉ mục, không lộn xộn với phân vùng và các công cụ được nêu ra .. đặc biệt với một hồ sơ millon, thats không có gì, tôi có bảng với hồ sơ 150 millon, và trở về 40k hồ sơ cụ thể mất động cơ khoảng 1500ms ...

+0

Quy trình chèn ngay bây giờ rất lỏng lẻo. Tôi không chèn số lượng lớn, vì vậy tôi tin rằng đó là vấn đề chính. Thật tuyệt khi đọc các con số từ các kích cỡ theo thời gian đã chọn, tôi không có biện pháp để biết cái gì là nhanh hay không. –

0

một giải pháp khác là tạo bảng lịch sử cho mỗi năm và đặt tất cả các bảng này trong cơ sở dữ liệu lịch sử, điền tất cả vào và sau đó tạo chỉ mục thích hợp cho chúng. Một khi bạn đã làm xong điều này, bạn sẽ không phải chạm vào chúng nữa. Tại sao bạn phải tiếp tục chèn dữ liệu? Để truy vấn tất cả các bảng đó, bạn chỉ cần "liên kết tất cả" chúng: p

Bảng năm hiện tại sẽ rất khác với các bảng lịch sử này. Đối với những gì tôi hiểu bạn đang có kế hoạch để chèn hồ sơ trên đường đi ?, Tôi muốn kế hoạch một cái gì đó khác nhau như làm một chèn số lượng lớn hoặc một cái gì đó tương tự mỗi bây giờ và sau đó cùng ngày. Tất nhiên tất cả điều này phụ thuộc vào những gì bạn muốn làm.

Các vấn đề ở đây dường như có trong thiết kế. Tôi muốn đi cho một thiết kế mới.Một trong những bạn có bây giờ cho những gì tôi hiểu nó không phù hợp.

+2

Không chuẩn hóa là lời khuyên xấu tại cơ sở dữ liệu kích thước này, và theo năm sẽ là sai cách anyway. – dkretz

1

Bạn đã đề cập rằng khóa chính của bạn là một hợp chất trên (Cổ phiếu, Ngày) và được nhóm lại. Điều này có nghĩa là bảng được sắp xếp theo Cổ phiếu và sau đó theo Ngày. Bất cứ khi nào bạn chèn một hàng mới, nó phải chèn nó vào giữa bảng, và điều này có thể làm cho các hàng khác được đẩy ra các trang khác (tách trang).

Tôi khuyên bạn nên cố gắng đảo ngược khóa chính thành (Ngày, Cổ phiếu) và thêm chỉ mục không được nhóm trên Cổ phiếu để tạo điều kiện tìm kiếm nhanh cho một Cổ phiếu cụ thể. Điều này sẽ cho phép chèn luôn luôn xảy ra ở cuối bảng (giả sử bạn đang chèn theo thứ tự ngày) và sẽ không ảnh hưởng đến phần còn lại của bảng và ít cơ hội chia tách trang hơn.

+0

Sai về việc đảo ngược chỉ mục được nhóm - các truy vấn dành cho nhiều cổ phiếu cùng một lúc, không phải nhiều ngày tại một thời điểm. Và chèn sẽ hoàn toàn không đáng kể tại 1 kỷ lục mới cho mỗi cổ phiếu mỗi ngày. – dkretz

+0

Thực ra tôi sẽ nhận được nhiều hơn 1 hồ sơ mới mỗi cổ phiếu mỗi ngày vì tôi sẽ bắt đầu lưu trữ mọi giao dịch cổ phiếu, có lẽ đây vẫn là một lời khuyên tốt? –

0

Thực tế chỉ mục chính tự động bị nén và tôi đã biến nó thành chỉ mục phức hợp với trường Cổ phiếu và Ngày. Điều này là duy nhất, tôi không thể có hai dữ liệu trích dẫn cho cùng một cổ phiếu trong cùng một ngày.

Chỉ số bị rỉ sét đảm bảo rằng các dấu ngoặc kép từ cùng một cổ phiếu ở lại với nhau và có thể được sắp xếp theo ngày. Thông tin thứ hai này có đúng không?

Chỉ mục trong SQL Server luôn được sắp xếp theo thứ tự cột trong chỉ mục. Vì vậy, một chỉ số về [cổ phiếu, ngày] đầu tiên sẽ sắp xếp trên cổ phiếu, sau đó trong kho vào ngày. Một chỉ mục về [ngày, chứng khoán] sẽ đầu tiên sắp xếp vào ngày, sau đó trong ngày trên cổ phiếu.

Khi thực hiện truy vấn, bạn nên luôn bao gồm (các) cột đầu tiên của chỉ mục trong phần WHERE, nếu không chỉ mục không thể sử dụng hiệu quả.

Đối với vấn đề cụ thể của bạn: Nếu truy vấn phạm vi ngày cho cổ phiếu là cách sử dụng phổ biến nhất, hãy thực hiện khóa chính vào [ngày, chứng khoán], vì vậy dữ liệu sẽ được lưu trữ theo ngày trên đĩa và bạn sẽ có quyền truy cập nhanh nhất . Xây dựng các chỉ mục khác nếu cần. Làm chỉ mục xây dựng lại/cập nhật số liệu thống kê sau khi chèn rất nhiều dữ liệu mới.

+0

SQL Server (và bất kỳ công cụ SQL nào khác) là quá khứ đủ thông minh để sắp xếp lại các trường của bạn để khớp với các chỉ mục, vì vậy thông tin khoản WHERE của bạn là vấn đề. Số liệu thống kê được cập nhật tự động. – dkretz

Các vấn đề liên quan