2009-02-17 18 views
5

Tôi đã nhảy múa quanh vấn đề này một lúc nhưng nó vẫn tiếp tục. Chúng tôi có một hệ thống và các bảng của chúng tôi có thể bắt đầu bằng mô tả ban đầu được lưu trữ dưới dạng NVARCHAR(150) và sau đó chúng tôi nhận được vé yêu cầu mở rộng kích thước trường lên 250, sau đó là 1000 v.v ...Cách duy trì để lưu trữ các trường văn bản lớn mà không làm mất hiệu suất là gì?

chu kỳ được lặp lại trên trường "ghi chú" và/hoặc trường "mô tả" mà chúng tôi thêm vào hầu hết các bảng. Tất nhiên mối quan tâm đối với tôi là hiệu suất và phá vỡ giới hạn 8k của trang. Tuy nhiên, mối quan tâm khác của tôi là làm cho hệ thống ít bảo trì hơn bằng cách phá vỡ các trường này ra khỏi bảng MỌI trong hệ thống thành một tham chiếu được nạp lười.

Vì vậy, ở đây tôi phải đối mặt với những điều tương tự với 2 tùy chọn đã được nhìn chằm chằm vào mặt tôi. (những người khác được chào đón) xin vui lòng cho tôi mượn ý kiến ​​của bạn.

  1. Thay đổi tất cả ghi chú và/hoặc mô tả thành NVARCHAR(MAX) và đảm bảo chúng tôi loại trừ các trường này trong tất cả các danh sách. Về cơ bản không bao giờ làm một: SELECT * FROM [TableName] trừ khi nó chỉ lấy một bản ghi.

  2. Xóa tất cả ghi chú và/hoặc trường mô tả và thay thế chúng bằng tham chiếu khóa forign thành bảng [Notes].

    CREATE TABLE [dbo].[Notes] (
    [NoteId] [int] NOT NULL,
    [NoteText] [NVARCHAR]
    (MAX) NOT NULL)

Rõ ràng là tôi muốn sử dụng phương án 1 vì nó sẽ thay đổi rất nhiều trong hệ thống của chúng tôi nếu chúng tôi đi với 2. Tuy nhiên, nếu phương án 2 thực sự là chỉ cách tốt để tiến hành, sau đó ít nhất tôi có thể nói những thay đổi này là cần thiết và tôi đã làm bài tập ở nhà.


CẬP NHẬT: Tôi đã chạy một vài thử nghiệm trên cơ sở dữ liệu mẫu với 100.000 bản ghi trong đó. Những gì tôi thấy là do chỉ số cluster quét IO cần thiết cho tùy chọn 1 là "gần" gấp hai lần tùy chọn 2. Nếu tôi chọn một số lượng lớn các bản ghi (1000 hoặc nhiều hơn) tùy chọn 1 là gấp đôi chậm ngay cả khi tôi làm không bao gồm trường văn bản lớn trong lựa chọn. Khi tôi yêu cầu ít hàng hơn các đường mờ hơn. Tôi là một ứng dụng web, nơi kích thước trang của 50 hoặc hơn là tiêu chuẩn, vì vậy tùy chọn 1 sẽ hoạt động, nhưng tôi sẽ chuyển đổi tất cả các trường hợp sang tùy chọn 2 trong tương lai gần (rất) cho khả năng mở rộng.

Trả lời

5

Lựa chọn 2 là tốt hơn vì nhiều lý do:

  1. Khi truy vấn bảng của bạn, lĩnh vực văn bản lớn lấp đầy các trang một cách nhanh chóng, buộc cơ sở dữ liệu để quét thêm trang để lấy dữ liệu. Đây là đặc biệt là thuế khi bạn không thực sự cần trả lại văn bản dữ liệu.
  2. Như bạn đã đề cập, nó cung cấp cho bạn một khoảng ngắt rõ ràng để thay đổi dữ liệu nhập một lần. Microsoft có không được chấp nhận TEXT trong SQL Server 2008, vì vậy bạn nên gắn bó với VARCHAR/VARBINARY.
  3. Các nhóm tệp riêng biệt. Có tất cả dữ liệu văn bản của bạn chậm hơn, vị trí lưu trữ rẻ hơn có thể là thứ bạn quyết định theo đuổi trong tương lai . Nếu không, không gây hại, không bị phạt số .

Khi tùy chọn 1 dễ dàng hơn bây giờ, tùy chọn 2 sẽ cung cấp cho bạn sự linh hoạt hơn trong thời gian dài. Đề xuất của tôi là triển khai một chứng minh đơn giản về khái niệm với thông tin "ghi chú" được tách ra khỏi bảng chính và thực hiện một số truy vấn của bạn trên cả hai ví dụ. So sánh các kế hoạch thực hiện, số liệu thống kê khách hàng và đọc I/O logic (SET STATISTICS IO ON) đối với một số truy vấn của bạn đối với các bảng này.

Một lưu ý nhanh chóng để những gợi ý việc sử dụng một TEXT/NTEXT từ MSDN:

Tính năng này sẽ được gỡ bỏ trong một phiên bản tương lai của Microsoft SQL Server. Tránh sử dụng tính năng này trong công việc phát triển mới và lập kế hoạch để sửa đổi các ứng dụng hiện đang sử dụng tính năng này. Thay vào đó, hãy sử dụng các loại dữ liệu varchar (max), nvarchar (max) và varbinary (max) . Để biết thêm thông tin, hãy xem xem Sử dụng các loại dữ liệu có giá trị lớn.

2

Tôi muốn đi với Lựa chọn 2.

Bạn có thể tạo một điểm cho rằng tham gia hai bảng để làm cho quá trình chuyển đổi dễ dàng hơn trên tất cả mọi người, và sau đó đi qua một quá trình dọn dẹp mà loại bỏ các quan điểm và sử dụng bảng đơn bất cứ nơi nào có thể.

1

Loại dữ liệu TEXT/NTEXT có độ dài không giới hạn thực tế trong khi chiếm gần không có gì trong hồ sơ của bạn.

Nó đi kèm với một vài chuỗi được đính kèm, như hành vi đặc biệt với các hàm chuỗi, nhưng đối với loại trường "ghi chú/mô tả" phụ, điều này có thể ít vấn đề hơn.

2

Bạn muốn sử dụng trường TEXT. Các trường TEXT không được lưu trực tiếp trong hàng; thay vào đó, nó lưu trữ một con trỏ đến dữ liệu văn bản. Tuy nhiên, điều này minh bạch đối với các truy vấn - nếu bạn yêu cầu một trường TEXT, nó sẽ trả về văn bản thực tế, chứ không phải con trỏ.

Về cơ bản, sử dụng trường TEXT có phần nằm giữa hai giải pháp của bạn.Nó giữ cho các hàng trong bảng của bạn nhỏ hơn nhiều so với việc sử dụng một varchar, nhưng bạn vẫn muốn tránh yêu cầu chúng trong các truy vấn nếu có thể.

1

Chỉ cần để mở rộng Lựa chọn 2

Bạn có thể:

Đổi tên MyTable hiện có để MyTable_V2

Move Notes cột vào một bảng ghi chú tham gia (với 1: 1 gia nhập ID)

Tạo VIEW được gọi là MyTable tham gia bảng MyTable_V2 và Ghi chú

Tạo một kích hoạt INSTEAD OF trên dạng xem MyTable để lưu cột Ghi chú vào bảng Ghi chú (IF NULL rồi xóa bất kỳ hàng Ghi chú hiện có nào, nếu NOT NULL rồi Chèn nếu không tìm thấy, nếu không Cập nhật).Thực hiện hành động thích hợp trên bảng MyTable_V2

Lưu ý: Chúng tôi đã gặp khó khăn khi thực hiện việc này khi có cột được tính trong MyTable_V2 (tôi nghĩ đó là vấn đề, theo cách này, chúng tôi đã gặp phải sự cố khi thực hiện điều này với bảng "bất thường")

Tất cả mới Insert/Update/Delete mã nên được ghi vào vận hành trực tiếp trên MyTable_V2 và Notes bảng

tùy ý: có CHÈN cÁC kích hoạt trên MyTable đăng nhập thực tế là nó đã được gọi là (nó có thể làm tối thiểu này , CẬP NHẬT hàng có sẵn trong bảng nhật ký với GetDate() chỉ khi ngày của hàng hiện tại là> 24 giờ - vì vậy sẽ chỉ cập nhật mỗi ngày một lần).

Khi bạn không còn nhận được bất kỳ bản ghi nhật ký nào, bạn có thể thả trình kích hoạt INSTEAD OF trên chế độ xem MyTable và bây giờ bạn hoàn toàn tuân thủ MyTable_V2!

Rất nhiều rắc rối để thực hiện, như bạn đã phỏng đoán.

Ngoài ra, hãy rà soát mã cho tất cả các tham chiếu đến MyTable và thay đổi chúng thành MyTable_V2, đặt VIEW ở vị trí của MyTable chỉ cho SELECT và không tạo trình kích hoạt INSTEAD OF.

Kế hoạch của tôi sẽ là sửa tất cả các câu lệnh Chèn/Cập nhật/Xóa tham chiếu MyTable không còn được dùng nữa. Đối với tôi, điều này sẽ được thực hiện dễ dàng hơn vì chúng tôi sử dụng tên duy nhất cho tất cả các bảng và cột trong cơ sở dữ liệu, và chúng tôi sử dụng cùng tên trong tất cả mã ứng dụng, vì vậy hãy đảm bảo rằng tôi đã tìm thấy tất cả các trường hợp bằng FIND đơn giản.

P.S. Tùy chọn 2 cũng thích hợp hơn nếu bạn có bất kỳ SELECT * nào nằm xung quanh. Chúng tôi đã có hiệu suất ứng dụng khách hàng whos đã đi xuống dốc nhanh khi họ thêm các cột Text/Blob lớn vào các bảng hiện có - vì các câu lệnh SELECT "lười". Hy vọng rằng đó không phải là trường hợp trong cửa hàng của bạn mặc dù!

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