Tinyint vs Bit?


81

Tôi không muốn khơi mào một cuộc chiến tôn giáo ở đây, nhưng dường như có hai trường phái suy nghĩ về cách biểu diễn các giá trị boolean trong cơ sở dữ liệu. Một số cho rằng đây bitlà kiểu dữ liệu thích hợp, trong khi những người khác cho rằng tinyinttốt hơn.

Sự khác biệt duy nhất mà tôi biết là:

  • bit: kích thước lưu trữ là 1 bit, các giá trị có thể là 0 hoặc 1
  • tinyint: kích thước lưu trữ là 1 byte, các giá trị có thể là 0-255

Kiểu dữ liệu nào tốt hơn khi bạn cần biểu diễn các giá trị boolean? Có tinyintgiá trị chi phí bổ sung "chỉ trong trường hợp" bạn cần giá trị> 1 không?


1
“Chỉ trong trường hợp” có vẻ giống như một thiết kế cơ sở dữ liệu khá linh hoạt. Tại sao không lưu trữ mọi thứ dưới dạng NVARCHAR (MAX) và bao gồm tất cả các căn cứ của bạn?
Stuart Ainsworth

TinyInt là sở thích của tôi. Sau đó, khi thực hiện các số lượng tổng hợp với trường, bạn không cần phải truyền nó. Ngoài ra, một số ngôn ngữ front-end diễn giải Bit khác với những ngôn ngữ khác và việc sử dụng TinyInt giúp kiểm tra xác thực phổ biến đối với bất kỳ ngôn ngữ front-end nào.
Gregory Hart

Tôi vừa gặp phải một sự kỳ lạ với bit trong phpMyAdmin. Khi tôi yêu cầu nó để trường là NULL và không có giá trị mặc định nào được đặt, nó sẽ mặc định là <em> NULL </em> thay vì NULL. +1 cho tinyint btw
Vörös Amadea 20/02/19

khi nhập tệp csv biểu mẫu 1 hoạt động trong trường hợp tinyint (1), nhưng trong trường hợp bit (1), bạn phải thay thế nó thành b'1 '
Rajat

Câu trả lời:


90

Khi bạn thêm một cột bit vào bảng của mình, nó sẽ chiếm toàn bộ byte trong mỗi bản ghi, không chỉ một bit đơn lẻ. Khi bạn thêm một cột bit thứ hai, nó sẽ được lưu trữ trong cùng một byte. Cột bit thứ chín sẽ yêu cầu byte lưu trữ thứ hai. Các bảng có cột 1 bit sẽ không đạt được bất kỳ lợi ích lưu trữ nào.

Tinyint và bit đều có thể được thực hiện để hoạt động, tôi đã sử dụng cả hai thành công và không có sở thích mạnh mẽ.


Đó là một nhận xét rất hữu ích và danh tiếng của bạn là khá tốt, nhưng bạn có bất kỳ tài liệu tham khảo để hỗ trợ nó? Nó có phải là một chi tiết triển khai hay tất cả các engine đều xử lý nó theo cùng một cách?
Jon z

3
@Jonz Xem tại đây cho MySQL.
shmosel

19

Bit ... trừ khi bạn thuộc nhóm "true / false / file not found"

Trong trường hợp bạn không nhận được tham chiếu ...

Và trong trường hợp của Linq2SQL, bit hoạt động với true / false nên việc lập trình dễ dàng hơn. Có lợi thế cho cả hai.

Và cũng có bảo trì lập trình để xem xét. Điều gì xảy ra nếu bạn (hoặc một lập trình viên mới thực tập) sử dụng 2, 3, 25, 41, 167, 200, v.v.? Tài liệu đó ở đâu? Bit tự ghi lại và khá phổ biến.


11
các bit là nullable nên bạn vẫn có thể có T / F / FNF.
Austin Salonen

3
Và điều ác như thế nào là NULL bằng FNF? :) Thực sự xứng đáng với thedailywtf!
John Rudy

@Pratik vấn đề là NULL có nghĩa là không có giá trị trong cơ sở dữ liệu. Nó không có nghĩa là không tìm thấy tệp. Làm điều này và bạn bắt đầu mã hóa ngầm các trạng thái thành các hàng khó ghi lại và khó hiểu. Kiểu như có một bảng các mục. Làm cách nào để biết một mặt hàng đã được bán chưa? Tôi có thể xem liệu nó có giá bán, ngày bán, tên người mua hay không, v.v. Hoặc tôi có thể thực thi tất cả những điều đó với ràng buộc kiểm tra và tạo một trường bit cho Các mặt hàng đã bán.
CodeMonkey

15

Tôi sử dụng bit khi thích hợp. Ngoài việc nó là loại chính xác về mặt ngữ nghĩa (đếm ngữ nghĩa!), Nhiều trường bit (tối đa 8) trong một hàng (dù sao trên SQL Server) có thể được hợp nhất thành một byte lưu trữ. Sau phần thứ tám, một byte bổ sung là cần thiết cho phần thứ 8 tiếp theo, v.v.

Người giới thiệu:




2

Boolean, theo định nghĩa, chỉ cho phép hai giá trị. Tại sao bạn cần bất cứ điều gì nhiều hơn một chút cho việc này? nếu bạn cần một lôgic trạng thái ba (hoặc nhiều hơn), thì hãy sử dụng một kiểu dữ liệu lớn hơn, nhưng tôi sẽ (và làm) gắn bó với các trường bit cho logic boolean tiêu chuẩn.


2

Tôi sử dụng bit vì nó giúp tôi tiết kiệm việc phải sử dụng ràng buộc kiểm tra và vì ORM của tôi sẽ tự động chuyển đổi bit thành boolean nullable (C #), điều mà tôi đánh giá rất cao sau khi mã hóa.


2

Không gian cho sai

Dù lựa chọn của bạn là gì, bạn có thể đặt thành NULLthay vì 0nó sẽ không chiếm thêm dung lượng (vì cơ sở dữ liệu hầu như luôn có NULLcờ cho mọi trường của mọi hàng, bạn chỉ cần ngồi ở đó; thêm thông tin tại đây ). Nếu bạn cũng đảm bảo giá trị mặc định / rất có thể là false, bạn sẽ tiết kiệm được nhiều dung lượng hơn!

Một số không gian cho sự thật

Giá trị để biểu diễn trueyêu cầu không gian được xác định bởi loại trường; việc sử dụng BITsẽ chỉ tiết kiệm dung lượng nếu một bảng có nhiều cột như vậy, vì nó sử dụng một byte trên 8 trường (so với TINYINTsử dụng một byte trên mỗi trường).

TINYINTcó ưu điểm là cho phép bạn tùy chỉnh mặt nạ bit 8 giá trị mà không cần lo lắng về việc quản lý nhiều cột thừa và tìm kiếm về mặt lý thuyết nhanh hơn (một trường số nguyên duy nhất so với một số trường bit). Nhưng có một số nhược điểm như đặt hàng chậm hơn, lập chỉ mục chéo lạ mắt và thiếu tên trường. Mà với tôi, là mất mát lớn nhất; cơ sở dữ liệu của bạn sẽ yêu cầu tài liệu bên ngoài để lưu ý các bit nào đã làm những gì trong các mặt nạ bit.

Trong mọi trường hợp, hãy tránh sự cám dỗ sử dụng TEXTcác trường để lưu trữ boolean hoặc tập hợp chúng. Tìm kiếm thông qua văn bản là công việc nhiều hơn cho máy chủ và các lược đồ đặt tên tùy ý như "bật, tắt, tắt" có thể ảnh hưởng đến khả năng tương tác.


1

Tôi vừa thử nhóm trên bit (SQL Server 2k5) và nó hoạt động tốt đối với tôi. Tôi thích sử dụng loại dữ liệu chính xác cho ứng dụng. Nếu đó là trường true / false, thì bit là thứ tôi sử dụng ...


1

Tất cả các cuộc thảo luận về mặt lý thuyết này đều tuyệt vời, nhưng trên thực tế, ít nhất nếu bạn đang sử dụng MySQL và thực sự cho SQLServer, thì tốt nhất bạn nên gắn bó với dữ liệu phi nhị phân cho boolean của mình vì lý do đơn giản là nó dễ làm việc hơn khi bạn đang xuất dữ liệu, truy vấn, v.v. Điều đặc biệt quan trọng nếu bạn đang cố gắng đạt được khả năng tương tác giữa MySQL và SQLServer (tức là bạn đồng bộ hóa dữ liệu giữa hai loại này), bởi vì việc xử lý kiểu dữ liệu BIT là khác nhau giữa hai loại. VẬY trong thực tế, bạn sẽ ít phức tạp hơn rất nhiều nếu bạn gắn bó với kiểu dữ liệu số. Tôi muốn khuyên MySQL gắn bó với BOOL hoặc BOOLEAN được lưu trữ dưới dạng TINYINT (1). Ngay cả cách MySQL Workbench và MySQL Administrator hiển thị kiểu dữ liệu BIT cũng không đẹp (nó là một biểu tượng nhỏ cho dữ liệu nhị phân).


1

Tôi không nghĩ rằng tôi đã thấy nó được đề cập ở trên, nhưng có vấn đề là không thể tổng hợp các cột BIT (ví dụ: MIN, MAX và đặc biệt là SUM). Tôi vừa thử nghiệm bằng cách sử dụng năm 2008 và sự cố vẫn còn đó. Đó là lý do lớn nhất mà tôi sử dụng tinyint gần đây - lý do khác là tôi thích cách quy mô tinyint - luôn là một vấn đề khó khăn khi cờ bit "hai giá trị" của bạn đột nhiên cần nhiều giá trị có thể hơn.


1
Bạn có thể tổng hợp chúng bằng cách truyền chúng sang một kiểu dữ liệu khác - Mặc dù vậy, tại sao bạn cần tính tổng true / false?
Martin Smith

2
Chúng tôi thường nhóm trên một trường và tổng hợp bao nhiêu trường khác đúng cho mỗi nhóm theo kết quả, giải pháp thay thế cho sum sẽ là trả về toàn bộ kết quả thành mã và lặp lại nó ở đó, đôi khi dẫn đến việc trả về dữ liệu gấp 1000 lần cho máy khách . Nhưng đúc loại bỏ điều đó để nó không phải là một vấn đề.
David Mårtensson

0

Chúng tôi xây dựng tất cả các bảng của mình với một trường int "vector". Sau đó, chúng tôi sử dụng trường đó như một tập hợp 32 bit mà chúng tôi có thể gán cho bất kỳ mục đích nào. (Có thể sử dụng một nhóm bit cho một tập hợp các trạng thái). Tránh việc chúng tôi phải tiếp tục thêm vào các trường cờ nếu chúng tôi quên.


2
Nó còn được gọi là obfuscation. Hoặc, đối với người thường, "cơn ác mộng bảo trì."
Robert C. Barth

6
Bạn chỉ có thể đặt tất cả các bảng của mình thành một cột VĂN BẢN duy nhất và đặt mọi thứ vào đó được phân tách bằng dấu phẩy. Sau đó, bạn sẽ không bao giờ phải thay đổi mô hình dữ liệu của mình.
Tom H

1
Chúng tôi có một môi trường hơi độc đáo. Chúng tôi có bộ dữ liệu cực kỳ lớn và thời gian hoạt động của AND 4 9, vì vậy việc thay đổi bảng là khá nghiêm trọng (gấp đôi so với khi có liên quan đến sao chép). Chúng tôi theo dõi tất cả các bit ở một vị trí tập trung, giúp tránh vấn đề bảo trì.
Joe

0

@Kevin: Tôi tin rằng bạn có thể sử dụng group bytrên các trường bit (SQL Server 2005):

declare @t table (
    descr varchar(10),
    myBit1 bit, 
    myBit2 bit
)
insert into @t values ('test1', 0, 1)
insert into @t values ('test2', 1, 0)
insert into @t values ('test3', 1, 1)
insert into @t values ('test4', 0, 0)

select myBit1, count(myBit1) from @t group by myBit1
select myBit2, count(myBit1) from @t group by myBit2

Các kết quả:

myBit1 
------ -----------
0      2
1      2

myBit2 
------ -----------
0      2
1      2

0

TinyInt là sở thích của tôi. Sau đó, khi thực hiện các số lượng tổng hợp với trường, bạn không cần phải truyền nó. Ngoài ra, một số ngôn ngữ front-end diễn giải Bit khác với những ngôn ngữ khác và việc sử dụng TinyInt giúp kiểm tra xác thực phổ biến cho bất kỳ ngôn ngữ front-end nào.



-2

Tôi thích sử dụng char (1) với 'T' hoặc 'F'. Có, nó có thể bị lạm dụng với các giá trị khác nhưng ít nhất nó cũng dễ xem trong báo cáo hoặc những nơi khác mà giá trị bit hoặc nhị phân khó làm việc hơn.


2
Bạn có thể (và nên) dễ dàng thêm một ràng buộc vào cột để chỉ cho phép "T" và "F". Điều đó đang được nói, lớp báo cáo phải được RIÊNG HOÀN TOÀN khỏi cơ sở dữ liệu. Bạn không nên thay đổi lược đồ cơ sở dữ liệu của mình chỉ vì mục đích cách một cột sẽ được hiển thị.
Tom H

Tôi đồng ý với Darryl. Do thiếu hỗ trợ cho các kiểu boolean trong các hệ thống RDBMS nói chung (MySQL không đơn độc ở đây) T / F (thực sự tôi thích Y / N hơn) dễ đọc hơn nhiều. Mặc dù tôi đồng ý về mặt nguyên tắc với nhận xét của Tom H, nhưng tôi nghĩ rằng khả năng dễ đọc quan trọng hơn nhiều so với việc anh ấy ghi công. Các nhà phát triển cơ sở dữ liệu không nhìn vào giao diện người dùng khi thay đổi mã của người khác! Ngoài ra, không nhất thiết phải luôn luôn rõ ràng cách mà nhà phát triển coi là 1 và 0. Nếu tất cả chúng ta đều làm điều đó theo cách cổ điển 'thích hợp', chúng ta sẽ sử dụng -1để biểu thị đúng và 0biểu thị sai.
cartbeforehorse

Đối với nhận xét trước đây của tôi, tôi nên nói thêm rằng có vẻ như MySQL không hỗ trợ ràng buộc CHECK, điều này sẽ làm phức tạp tùy chọn T / F, vì bạn không thể ngăn cột được điền bởi bất kỳ ký tự nào khác của bảng chữ cái. Không hay.
cartbeforehorse
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.