Khi nào nên sử dụng TINYINT trên INT?


91

Nói chung, tôi luôn sử dụng Ints. Tôi biết rằng trên lý thuyết, đây không phải là cách thực hành tốt nhất, vì bạn nên sử dụng loại dữ liệu nhỏ nhất sẽ được đảm bảo để lưu trữ dữ liệu.

Ví dụ, sẽ tốt hơn tinyintkhi sử dụng khi bạn biết rằng dữ liệu duy nhất bạn sẽ lưu trữ là 1, 0 hoặc null (với cơ hội rất nhỏ để mở rộng dữ liệu đó thành 2 hoặc 3 sau).

Tuy nhiên, lý do duy nhất tôi biết để làm điều này là cho mục đích lưu trữ - sử dụng 1 byte trên một hàng thay vì 4 byte.

Những tác động của việc sử dụng tinyint(hoặc smallintthậm chí bigint) đối với chỉ int, ngoài việc tiết kiệm dung lượng trên ổ cứng của bạn là gì?


2
Đây là một quesiton rất đẹp (+1). MySQL có CHỌN ... THỦ TỤC ANALYZE () thực sự khuyến nghị các loại dữ liệu nhỏ nhất mà bảng nên có cho CHỌN đã cho. Đó là một phần cảm hứng đằng sau câu trả lời của tôi.
RolandoMySQLDBA

3
Câu hỏi hay, nhưng để chính xác phạm vi tinyint là 0-255. Trường bit là 0 hoặc 1 (hoặc NULL). Chi phí lưu trữ cho một tinyint là 1 byte. Mỗi trường 8 bit trong một bảng sẽ tốn 1 byte dung lượng lưu trữ. msdn.microsoft.com/en-us/l
Library / ms187745.aspx

@billinkc Đúng rồi. Đó là lý do tại sao tôi đề cập đến khả năng mở rộng cột để bao gồm các giá trị 2 hoặc 3. Nếu bạn bao gồm 2 hoặc 3, bạn phải sử dụng tinyint (ở quy mô rất nhỏ).
Richard

1
"Ví dụ: tốt hơn là sử dụng tinyint khi bạn biết rằng dữ liệu duy nhất bạn sẽ lưu trữ là 1, 0 hoặc null (với cơ hội rất nhỏ để mở rộng dữ liệu đó thành 2 hoặc 3 sau)." Tôi sẽ sử dụng một ENUM cho một điều như vậy. Chúng được lưu trữ dưới dạng bitfield và như nhiều người khác đã chỉ ra ở đây, các khoản tiết kiệm nhỏ trên mỗi bản ghi cộng với khoản tiết kiệm lớn trên toàn bộ cơ sở dữ liệu - thậm chí ngay cả khi cột được lập chỉ mục.

2
@ user6665 I'd use an ENUM for such a thing.Không có trong SQL Server, bạn sẽ không, vì nó không có bất kỳ loại nào.
gạch dưới

Câu trả lời:


92

Dung lượng ổ đĩa rẻ ... đó không phải là vấn đề!

Ngừng suy nghĩ về không gian lưu trữ, thay vào đó hãy nghĩ về vùng đệm và băng thông lưu trữ . Cuối cùng, bộ nhớ cache CPU và băng thông bus bộ nhớ . Bài viết được liên kết là một phần của loạt vấn đề làm nổi bật với lựa chọn khóa cụm kém (INT vs GUID so với GUID tuần tự) nhưng nó làm nổi bật các byte khác nhau có thể tạo ra.

Thông điệp ghi đè là vấn đề thiết kế. Sự khác biệt sẽ không xuất hiện trong một cơ sở dữ liệu riêng lẻ trên một máy chủ cụ thể phù hợp cho đến khi bạn truy cập vào lãnh thổ VLDB nhưng nếu bạn có thể lưu một vài byte, tại sao không làm như vậy.

Tôi nhắc nhở về môi trường được mô tả trong một câu hỏi trước đó . Hơn 400 cơ sở dữ liệu, có kích thước từ 50mb-50GB, mỗi phiên bản SQL. Việc xóa một vài byte trên mỗi bản ghi, trên mỗi bảng, trên mỗi cơ sở dữ liệu trên môi trường đó có thể tạo ra sự khác biệt đáng kể.


29

Ngoài những câu trả lời khác ...

Hàng và mục chỉ mục được lưu trữ trong các trang 8k. Vì vậy, một triệu hàng ở 3 byte mỗi hàng không phải là 3 MB trên đĩa: nó ảnh hưởng đến số lượng hàng trên mỗi trang ("mật độ trang").

Điều tương tự cũng áp dụng cho nvarchar cho varchar, smalldatetime đến datetime, int to tinyint v.v.

Chỉnh sửa, tháng 6 năm 2013

http://sqlblog.com/bloss/joe_chang/archive/2013/06/16/load-test-manifesto.aspx

Bài viết này nêu

Các tiêu chí quan trọng là tỷ lệ cardinality và tỷ lệ trang trên hàng.

Vì vậy, lựa chọn loại dữ liệu có vấn đề


5
Điểm tốt. Một ví dụ trường hợp xấu nhất tuyệt đối là một hàng 4028 byte bao gồm các cột có độ dài hoàn toàn cố định mà bạn muốn thêm một cột vào. Thêm một phần nhỏ sẽ đưa bạn đến 4030 (2 hàng trên mỗi trang) nhưng một int sẽ đẩy bạn qua ranh giới (1 hàng trên mỗi trang, 4028 byte bị lãng phí trên mỗi trang).
Mark Storey-Smith

Tôi đã từng làm một bài kiểm tra hiệu suất trên int vs bigint. Lưu 1 triệu bản ghi, so sánh thời gian và lưu trữ và truy xuất từng cái một, một lần nữa đo hiệu suất. Tôi không thấy sự khác biệt lớn. Tôi sẽ làm bài kiểm tra hiệu năng tương tự cho int vs tinyint. Tôi thực sự nghĩ rằng nó có thể bị bỏ qua cho 80% các ứng dụng, dẫn đến các loại dữ liệu phù hợp hơn và chi phí bảo trì thấp hơn.
Saeed Neamati

1
@SaeedNeamati Bạn có thể muốn đọc lại bài viết từ câu trả lời của Mark (" Bạn đã bao giờ nghe ... hãy hoàn thành nó - chúng ta sẽ lo lắng về hiệu suất sau này? ... Tôi nghe thấy điều này suốt thời gian ") và gbn ở đây . Tôi nghĩ rằng việc mang về nhà là bất kỳ sự lựa chọn không hiệu quả nào cũng sẽ hiển thị các sọc của nó ở đúng tỷ lệ và ruột của OP không sai.
ruffin

14

Đó không chỉ là lưu trữ bảng mà là một sự cân nhắc. Nếu bạn sử dụng các chỉ mục trong đó cột int là một phần của khóa ghép, bạn sẽ tự nhiên muốn các trang chỉ mục càng đầy đủ càng tốt, đây là kết quả của các mục chỉ mục càng nhỏ càng tốt.

Tôi chắc chắn sẽ mong đợi rằng việc kiểm tra các mục chỉ mục trong các trang BTREE sẽ nhanh hơn một chút với các loại dữ liệu nhỏ hơn. Tuy nhiên, bất kỳ VARCHAR nào liên quan đến các mục chỉ mục sẽ bù đắp (vô hiệu hóa) hiệu suất đạt được từ việc sử dụng TINYINT trên INT.

Mặc dù vậy, nếu các mục chỉ mục có các mục tổng hợp và tất cả đều là số nguyên, số nguyên càng nhỏ thì càng tốt, càng tốt và càng nhanh.


13

Tất cả mọi thứ trở nên phức tạp khi cơ sở dữ liệu trở nên lớn hơn:

  • cửa sổ bảo trì cần phải được mở rộng hoặc sắp xếp lại
  • sao lưu (sao lưu toàn bộ vào cuối ngày trở thành một công cụ tiết kiệm thời gian vô lý, vì vậy bạn cần một bản sao lưu khác biệt hoặc thậm chí đăng nhập và thực hiện đầy đủ một lần một tuần, có thể mỗi tháng một lần)
  • bảo trì biểu diễn trở thành một người ăn thời gian (tạo một chỉ mục trên bảng nhiều triệu hàng không mất thời gian để thực hiện) và cần được lên lịch lại và trở nên tồi tệ hơn nếu bảng rộng ...
  • Và việc truyền bản sao lưu 100Gb đó qua mạng không phải là thứ tôi gọi là một miếng bánh - đặc biệt nếu mạng (vì một lý do không xác định nào đó) bướng bỉnh trong việc làm mất kết nối trên dấu 75Gb ... (xảy ra với cài đặt tôi đang làm việc đã sao lưu vào một ổ đĩa được ánh xạ trên mạng - mạng) ...

Và những kiểu dữ liệu phải làm với điều đó? MỌI ĐIỀU. Việc sử dụng kích thước hàng lớn hơn mức cần thiết sẽ khiến các trang cơ sở dữ liệu điền trước hơn mức cần thiết hoặc thậm chí lãng phí dung lượng nếu kích thước hàng sao cho không có nhiều hơn một bản ghi có thể được ghi trên trang. Kết quả là cần nhiều trang hơn để viết và đọc, bộ nhớ RAM được sử dụng nhiều hơn để lưu trữ bộ đệm đó (bản ghi lớn hơn cần bộ nhớ lớn hơn). Và vì các kiểu dữ liệu của bạn được chỉ định lớn hơn mức cần thiết từ đĩa, các chỉ mục của bạn sẽ gặp cùng một vấn đề - đặc biệt nếu bạn gom cụm khóa chính 2 cột BIGINT vì bất kỳ chỉ mục nào khác được tạo sẽ sao chép khóa chính đó theo định nghĩa của chúng.

Nếu bạn biết rằng một số cột trong một bảng sẽ có hàng triệu hàng hoặc thậm chí một bảng nhỏ sẽ chuyển thành nhiều triệu hàng không cần số nguyên 4 byte để lưu trữ dữ liệu của họ, nhưng 2 byte sẽ đủ - sử dụng SMALLINT . Nếu các giá trị trong phạm vi 0-255 là đủ, TINYINT . Có / Không cờ? Có BIT .


9

Mặc dù đối tinyintvới vs intcó sự khác biệt rõ ràng như dung lượng ổ đĩa, phân chia trang và thời gian bảo trì, nhưng sẽ không có bất kỳ sự khác biệt nào trong số này varchar.

Vậy tại sao không khai báo tất cả các trường văn bản như varchar(4000), vì dù sao nó sẽ chỉ sử dụng hết dung lượng cần thiết? Thậm chí nhiều hơn bạn sẽ được đảm bảo rằng dữ liệu của bạn sẽ không bao giờ bị cắt ngắn.

Câu trả lời là tất nhiên:

  1. Làm rõ ý định của bạn (vì sẽ không ai hiểu tại sao trường tên phải là 4000 ký tự)
  2. Xác nhận khi bạn muốn đảm bảo không ai nhập toàn bộ tiểu sử làm tên.

Những lý do rất giống nhau áp dụng cho tinyintlà tốt.


3
Đây là một chủ đề cũ hơn, nhưng làm rõ và xác nhận không phải là lý do duy nhất. Nếu bạn có VARCHAR (4000) cho thứ gì đó phải là VARCHAR (20), kế hoạch truy vấn sẽ nghĩ rằng các yêu cầu về bộ nhớ và CPU của bạn là nhiều bội số của những gì chúng nên liên quan đến cột đó. Tôi đã không dành thời gian để làm điều này, nhưng tôi đoán rằng bạn có thể thấy điều này bằng cách xem kế hoạch truy vấn cho VARCHAR (20) và sau đó đổi thành VARCHAR (4000) và kiểm tra chi phí ước tính.

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.