Kiểu dữ liệu MySQL cho số nguyên 128 bit


12

Tôi cần lưu trữ 128 số nguyên không dấu vào MySQL và tôi đã tự hỏi đâu là loại dữ liệu tốt nhất để lưu trữ số lượng lớn như vậy.

Ngay bây giờ, tôi đang sử dụng binary(16)nhưng liên quan đến rất nhiều chức năng chuyển đổi pack(/huge number in hex .../).

Có một kiểu dữ liệu tốt nhất để lưu trữ một số nguyên không dấu 128 bit không?


4
Tôi không thể không chú ý đây là câu hỏi thứ hai trong đó có vẻ như bạn phải làm những điều kỳ lạ với giải pháp của mình để có thể sử dụng MySql. Bạn đã xem xét một nền tảng DB mạnh mẽ hơn?
Russell Steen

Tôi có xu hướng nhìn để xem FORTRAN và các ngôn ngữ khác hỗ trợ số nguyên 64 bit khi chúng tôi vẫn đang xử lý các hệ thống 8 & 16 bit.
Joe

@Russel Steen, bạn muốn giới thiệu gì và là một nền tảng DB mạnh mẽ hơn?
Kami

Bạn vẫn sẽ cần phải đóng gói và giải nén nó nhưng Postgres có loại 128 bit gốc .
Gaius

Trên thực tế, loại bigserial Postgres nên làm điều đó.
Gaius

Câu trả lời:


10

Tôi không biết cách tốt nhất nhất là lưu trữ nó - nhưng ít nhất có một lựa chọn tốt hơn so với sử dụng varchar(39)(hoặc varchar(40)nếu bạn cần ký tên); thay vì sử dụng a decimal(39,0). Từ các tài liệu mysql :

Các loại điểm cố định (chính xác-giá trị)

Các loại DECIMAL và NUMERIC lưu trữ các giá trị dữ liệu số chính xác. Các loại này được sử dụng khi điều quan trọng là bảo toàn độ chính xác chính xác, ví dụ với dữ liệu tiền tệ. Trong MySQL, NUMERIC được triển khai dưới dạng DECIMAL, do đó, các nhận xét sau đây về DECIMAL cũng áp dụng tương tự cho NUMERIC.

MySQL 5.1 lưu các giá trị DECIMAL ở định dạng nhị phân. Trước MySQL 5.0.3, chúng được lưu trữ dưới dạng chuỗi. Xem Phần 11,18, Chính xác Toán Toán.

Trong một khai báo cột DECIMAL, độ chính xác và tỷ lệ có thể được (và thường là) được chỉ định; ví dụ:

salary DECIMAL(5,2)

Trong ví dụ này, 5 là độ chính xác và 2 là thang đo. Độ chính xác đại diện cho số chữ số có nghĩa được lưu trữ cho các giá trị và thang đo biểu thị số chữ số có thể được lưu trữ sau dấu thập phân.

SQL tiêu chuẩn yêu cầu DECIMAL (5,2) có thể lưu trữ bất kỳ giá trị nào với năm chữ số và hai số thập phân, do đó, các giá trị có thể được lưu trữ trong phạm vi cột lương từ -999,99 đến 999,99.

Trong SQL tiêu chuẩn, cú pháp DECIMAL (M) tương đương với DECIMAL (M, 0). Tương tự, cú pháp DECIMAL tương đương với DECIMAL (M, 0), trong đó việc triển khai được phép quyết định giá trị của M. MySQL hỗ trợ cả hai dạng cú pháp DECIMAL biến thể này. Giá trị mặc định của M là 10.

Nếu tỷ lệ là 0, các giá trị DECIMAL không chứa phần thập phân hoặc phần phân số.

Số chữ số tối đa cho DECIMAL là 65, nhưng phạm vi thực tế cho một cột DECIMAL nhất định có thể bị hạn chế bởi độ chính xác hoặc tỷ lệ cho một cột nhất định. Khi một cột như vậy được gán một giá trị có nhiều chữ số theo dấu thập phân hơn mức cho phép theo tỷ lệ được chỉ định, giá trị được chuyển đổi sang tỷ lệ đó. (Hành vi chính xác là đặc thù của hệ điều hành, nhưng nhìn chung hiệu ứng là cắt bớt số chữ số cho phép.)

Nó được lưu trữ đóng gói, vì vậy nó sẽ chiếm ít không gian hơn so với varchar ( 18 byte, nếu tôi thực hiện đúng phép toán của mình ) và tôi hy vọng bạn có thể trực tiếp làm toán trên nó, nhưng tôi không bao giờ thử với số lượng lớn đó để xem điều gì sẽ xảy ra.


8

Tôi thấy mình hỏi câu hỏi này và từ tất cả các bài viết tôi đọc không bao giờ tìm thấy bất kỳ so sánh hiệu suất. Vì vậy, đây là nỗ lực của tôi.

Tôi đã tạo các bảng sau, được điền với 2.000.000 địa chỉ IP ngẫu nhiên từ 100 mạng ngẫu nhiên.

CREATE TABLE ipv6_address_binary (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr BINARY(16) NOT NULL UNIQUE
);

CREATE TABLE ipv6_address_twobigints (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    haddr BIGINT UNSIGNED NOT NULL,
    laddr BIGINT UNSIGNED NOT NULL,
    UNIQUE uidx (haddr, laddr)
);

CREATE TABLE ipv6_address_decimal (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr DECIMAL(39,0) NOT NULL UNIQUE
);

Sau đó, tôi CHỌN tất cả các địa chỉ IP cho mỗi mạng và ghi lại thời gian phản hồi. Thời gian phản hồi trung bình trên bảng twobigint là khoảng 1 giây trong khi trên bảng nhị phân là khoảng một phần trăm giây.

Dưới đây là các truy vấn.

Ghi chú:

X_ [CAO / THẤP] là 64 bit quan trọng nhất / ít nhất của X

khi NETMASK_LOW bằng 0, điều kiện AND bị bỏ qua vì nó luôn mang lại kết quả đúng. không ảnh hưởng đến hiệu suất rất nhiều.

SELECT COUNT(*) FROM ipv6_address_twobigints
WHERE haddr & NETMASK_HIGH = NETWORK_HIGH
AND laddr & NETMASK_LOW = NETWORK_LOW

SELECT COUNT(*) FROM ipv6_address_binary
WHERE addr >= NETWORK
AND addr <= BROADCAST

SELECT COUNT(*) FROM ipv6_address_decimal
WHERE addr >= NETWORK
AND addr <= BROADCAST

Thời gian phản hồi trung bình:

Thời gian phản hồi trung bình

BINARY_InnoDB  0.0119529819489
BINARY_MyISAM  0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB  0.782350552082
BIGINT_MyISAM  1.07809265852

2

Tôi tin rằng lựa chọn duy nhất khác là lưu trữ nó trong một varchar(39)lĩnh vực.


2
Tôi nghĩ rằng điều này sẽ làm việc nếu bạn chỉ muốn lưu trữ dữ liệu.
eiefai

1
@eiefai: Không phải đó là những gì anh ấy hỏi sao? "Tôi cần lưu trữ số nguyên không dấu 128 bit"
BenV

Ồ vâng, đây là lời khuyên tốt, tôi chỉ nhận xét để đảm bảo rằng anh ta chỉ muốn lưu trữ chứ không phải làm một số calcs.
eiefai

@eiefai: ah ok, tôi hiểu lầm. Bạn hoàn toàn đúng, giá trị sẽ phải được bỏ trước khi nó có thể được coi là một số.
BenV
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.