2010-12-26 14 views
6

Tôi đã nhìn thấy một số phương pháp có thể (trong một số công cụ cơ sở dữ liệu một số trong số đó là từ đồng nghĩa):Cách tối ưu để lưu trữ cờ nhị phân/giá trị boolean trong mỗi công cụ cơ sở dữ liệu là gì?

  1. TINYINT (1)
  2. BOOL
  3. BIT (1)
  4. ENUM (0,1)
  5. CHAR (0) NULL

Tất cả các cơ sở dữ liệu lớn được hỗ trợ bởi PHP cần lưu ý, nhưng cũng giống như một refference nó sẽ là tốt hơn nếu cũng o có động cơ sẽ được lưu ý.

Tôi yêu cầu thiết kế là được tối ưu hóa tốt nhất để đọc. ví dụ: Chọn bằng cờ trong điều kiện WHERE hoặc GROUP BY flag. Hiệu suất quan trọng hơn nhiều so với dung lượng lưu trữ (trừ khi kích thước có tác động đến hiệu suất).

Và một số chi tiết:

Trong khi tạo bảng tôi không thể biết nếu nó sẽ thưa thớt (nếu hầu hết cờ bật hoặc tắt), nhưng tôi có thể làm thay đổi bảng sau này, vì vậy nếu có là thứ tôi có thể tối ưu hóa nếu tôi biết điều đó, cần lưu ý.

Ngoài ra nếu nó tạo sự khác biệt nếu chỉ có một cờ (hoặc một vài) cho mỗi hàng, so với nhiều (hoặc nhiều) cờ cần lưu ý.

BTW, tôi đã đọc ở đâu đó trong SO sau:

Sử dụng boolean có thể làm điều tương tự như sử dụng tinyint, tuy nhiên nó có Ưu điểm của ngữ nghĩa truyền đạt gì ý định của bạn là gì, và đó là đáng giá.

Vâng, trong trường hợp của tôi, nó không có giá trị gì, bởi vì mỗi bảng được đại diện bởi một lớp trong ứng dụng của tôi và mọi thứ được xác định rõ ràng trong lớp học và tài liệu.

Trả lời

6

Câu trả lời này là dành cho SQL tiêu chuẩn ISO/IEC/ANSI và bao gồm các phần mềm giả vờ-phần mềm miễn phí tốt hơn.

Vấn đề đầu tiên là bạn đã xác định hai Danh mục, chứ không phải một danh mục, vì vậy chúng không thể được so sánh một cách hợp lý.

A. Loại One

(1) (4) và (5) chứa nhiều giá trị có thể và là một danh mục. Tất cả có thể được sử dụng dễ dàng và hiệu quả trong mệnh đề WHERE. Chúng có cùng dung lượng để lưu trữ và hiệu suất đọc không phải là vấn đề. Do đó, lựa chọn còn lại đơn giản dựa trên Datatype thực tế cho mục đích của cột.

ENUM không chuẩn; phương pháp tốt hơn hoặc tiêu chuẩn là sử dụng bảng tra cứu; sau đó các giá trị được hiển thị trong bảng, không bị ẩn và có thể được liệt kê bởi bất kỳ công cụ báo cáo nào. Hiệu suất đọc của ENUM sẽ bị ảnh hưởng nhỏ do xử lý nội bộ.

B. Danh mục Hai

(2) và (3) là hai yếu tố có giá trị: Đúng/Sai; Nam nữ; Xác sống. Danh mục đó khác với Danh mục Một. Điều trị của nó cả trong mô hình dữ liệu của bạn, và trong mỗi nền tảng, là khác nhau. BOOLEAN chỉ là một từ đồng nghĩa với BIT, chúng giống nhau. Về mặt pháp lý (SQL-khôn ngoan) được xử lý giống nhau bởi tất cả các nền tảng tuân thủ SQL, và không có vấn đề gì khi sử dụng nó trong mệnh đề WHERE.

Sự khác biệt về hiệu suất phụ thuộc vào nền tảng. Sybase và DB2 đóng gói tới 8 BIT thành một byte (không phải là lưu trữ quan trọng ở đây), và ánh xạ năng lượng-của-hai khi đang bay, vì vậy hiệu năng thực sự tốt.Oracle làm những việc khác nhau trong mỗi phiên bản, và tôi đã thấy các modellers sử dụng CHAR (1) thay vì BIT, để khắc phục các vấn đề về hiệu năng. MS đã được phạt đến năm 2005 nhưng họ đã phá vỡ nó với năm 2008, như trong kết quả là không thể đoán trước; vì vậy câu trả lời ngắn có thể là thực hiện nó như CHAR (1).

Tất nhiên, giả định là bạn không làm những điều ngớ ngẩn như gói 8 cột riêng biệt trong một TINYINT. Không chỉ là một lỗi bình thường nghiêm trọng, nó là một cơn ác mộng đối với các lập trình viên. Giữ mỗi cột rời rạc và đúng Datatype.

C. Nhiều chỉ số & Cột Nullable

này không có gì để làm với, và không phụ thuộc, (A) và (B). Những cột đúng Datatype là, là riêng biệt với bao nhiêu bạn có và cho dù đó là Nullable. Nullable phương tiện (thường) cột là tùy chọn. Về cơ bản bạn đã không hoàn thành việc mô hình hóa hoặc tập thể dục bình thường hóa. Các phụ thuộc chức năng không rõ ràng. nếu bạn hoàn thành bài tập Bình thường hóa, sẽ không có các cột không thể bỏ qua, không có cột tùy chọn; hoặc chúng tồn tại rõ ràng cho một mối quan hệ cụ thể, hoặc chúng không tồn tại. Điều đó có nghĩa là sử dụng cấu trúc quan hệ thông thường của Supertype-Subtypes.

Chắc chắn, điều đó có nghĩa là nhiều bảng hơn, nhưng không có Null. Enterpise DBMS không có vấn đề với nhiều bảng hơn hoặc nhiều hơn tham gia, đó là những gì họ được tối ưu hóa cho. Các cơ sở dữ liệu được chuẩn hóa thực hiện tốt hơn nhiều so với các cơ sở dữ liệu không chuẩn hóa hoặc không chuẩn hóa, và chúng có thể được mở rộng mà không cần phải "tái thanh toán" Bạn có thể dễ dàng sử dụng bằng cách cung cấp một View cho mỗi Subtype. tại question/answer này. Nếu bạn cần giúp đỡ với các mô hình, hãy hỏi một câu hỏi mới. ở cấp lại đặt câu hỏi, tôi sẽ khuyên bạn gắn bó với 5NF.

D. hiệu suất của Nulls

riêng, nếu hiệu suất Mỗi cột Nullable được lưu trữ dưới dạng độ dài thay đổi, yêu cầu xử lý bổ sung cho mỗi hàng/cột. s sử dụng xử lý "trì hoãn" cho các hàng như vậy, để cho phép ghi nhật ký, v.v. di chuyển suy nghĩ các hàng đợi mà không cản trở các hàng cố định. Cụ thể không bao giờ sử dụng các cột có độ dài biến đổi (bao gồm các cột có thể bỏ qua) trong một Chỉ mục: yêu cầu giải nén trên mọi quyền truy cập.

E. Thăm dò ý kiến ​​

Cuối cùng, tôi không thấy điểm trong câu hỏi này là cuộc thăm dò ý kiến. Nó đủ công bằng mà bạn sẽ nhận được câu trả lời kỹ thuật và thậm chí cả ý kiến, nhưng cuộc thăm dò ý kiến ​​cho các cuộc thi phổ biến và khả năng kỹ thuật của người trả lời tại SO bao gồm rất nhiều, vì vậy câu trả lời phổ biến nhất và câu trả lời chính xác nhất là hai câu hỏi khác nhau kết thúc của quang phổ.

+0

Bạn có thể bao gồm liên kết hoặc thông tin thêm về cách "MS được xử lý đến năm 2005 nhưng đã phá vỡ năm 2008, vì kết quả là không thể đoán trước" và nếu nó bị hỏng trong 2K8R2 –

+2

@RC. Tôi không có liên kết, tôi có kinh nghiệm. Wiki chưa từng nghe về nó. Kết quả của bối cảnh cụ thể ở trên và một số trường hợp khác, không phải tất cả các ngữ cảnh đều không thể đoán trước được; nếu bạn có mã hoạt động tốt dưới năm 2005. Tôi đã đăng một số chi tiết cụ thể khác: xóa các trang tràn và làm tổn thương tất cả hiệu suất trên các chỉ mục Nhóm, v.v. Hãy đọc chúng. Không cố định trong Rev 2. Không có khả năng những yếu tố này được sửa cho đến khi Rev 4 ít nhất. Phải mất MS hơn 3 năm để sửa chữa năm 2005. – PerformanceDBA

1

Tôi biết đây không phải là câu trả lời bạn muốn, nhưng sự khác biệt thực sự là không đáng kể trong tất cả trừ trường hợp đặc biệt khắc nghiệt nhất. Và trong mỗi trường hợp cụ thể như vậy, chỉ cần chuyển đổi kiểu dữ liệu sẽ không đủ để khắc phục sự cố hiệu suất.

Ví dụ: dưới đây là một số lựa chọn thay thế sẽ hoạt động tốt hơn bất kỳ thay đổi kiểu dữ liệu nào theo một yếu tố lớn. Mỗi mang với một nhược điểm của khóa học.

Nếu bạn có 200 cờ tùy chọn và bạn truy vấn tối đa 1-2 tại một thời điểm cho nhiều hàng, bạn sẽ nhận được hiệu suất tốt hơn bằng cách có từng cờ trong bảng riêng của mình. Nếu dữ liệu thực sự thưa thớt, điều này càng trở nên tốt hơn.

Nếu bạn có 200 cờ bắt buộc và bạn chỉ thực hiện tìm nạp bản ghi duy nhất, bạn nên đặt chúng trong cùng một bảng.

Nếu bạn có một nhóm cờ nhỏ, bạn có thể gói chúng trong một cột bằng cách sử dụng bitmask, lưu trữ hiệu quả một cách khôn ngoan, nhưng bạn sẽ không thể (dễ dàng) truy vấn các cờ riêng lẻ. Tất nhiên, điều này không hoạt động khi cờ có thể là NULL ...

Hoặc bạn có thể sáng tạo và sử dụng khái niệm "thứ nguyên rác", trong đó bạn tạo một bảng riêng biệt với tất cả 200 cờ boolean được biểu diễn dưới dạng cột. Tạo một hàng cho mỗi kết hợp giá trị cờ riêng biệt. Mỗi hàng có một khóa chính tự động, mà bạn tham chiếu trong bản ghi chính. Thì đấy, bảng tổng thể hiện chứa 1 int, thay vì 200 cột. Tin tặc trời, cơn ác mộng DBA.

Điểm tôi đang cố gắng thực hiện là mặc dù điều thú vị là tranh luận về "điều tốt nhất", có những mối quan tâm khác có tầm quan trọng lớn hơn nhiều (như nhận xét bạn trích dẫn). Đơn giản vì khi bạn gặp phải một vấn đề hiệu năng thực sự, kiểu dữ liệu sẽ không phải là vấn đề hay giải pháp.

0

Bất kỳ điều nào ở trên đều tốt và tôi có sở thích cá nhân sử dụng BOOL nếu nó được hỗ trợ đúng cách vì tốt nhất truyền đạt ý định của bạn nhưng tôi sẽ tránh sử dụng ENUM(0,1).

Vấn đề đầu tiên với ENUM là yêu cầu giá trị của nó phải là một chuỗi. 01 trông giống như một con số để các lập trình viên có khuynh hướng gửi một số.

Vấn đề thứ hai với ENUM là nếu bạn gửi sai giá trị mặc định cho liệt kê đầu tiên và trong một số cơ sở dữ liệu, nó thậm chí sẽ không báo lỗi (tôi đang xem bạn MySQL). Điều này làm cho vấn đề đầu tiên tồi tệ hơn nhiều kể từ khi bạn vô tình gửi nó 1 thay vì "1" nó sẽ lưu trữ giá trị "0" - rất phản trực quan!

Tôi không nghĩ rằng điều này ảnh hưởng đến tất cả các công cụ cơ sở dữ liệu (không biết, havent't đã thử tất cả) nhưng nó ảnh hưởng đến đủ của họ mà tôi xem xét tránh nó là thực hành tốt.

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