ชนิดข้อมูล MySQL สำหรับจำนวนเต็ม 128 บิต


12

ฉันต้องการจัดเก็บจำนวนเต็ม 128 บิตที่ไม่มีเครื่องหมายใน MySQL และฉันสงสัยว่าประเภทข้อมูลที่ดีที่สุดในการจัดเก็บจำนวนมากนั้นคืออะไร

ตอนนี้ผมใช้แต่ที่เกี่ยวข้องกับหลายฟังก์ชั่นแปลงbinary(16)pack(/huge number in hex .../)

มีประเภทข้อมูลที่ดีที่สุดในการจัดเก็บจำนวนเต็ม 128 บิตที่ไม่ได้ลงชื่อ?


4
ฉันอดไม่ได้ที่จะสังเกตว่านี่เป็นคำถามที่สองที่ดูเหมือนว่าคุณต้องทำสิ่งแปลก ๆ กับโซลูชันของคุณเพื่อที่จะใช้ MySql ได้ คุณคิดว่าเป็นแพลตฟอร์มฐานข้อมูลที่แข็งแกร่งกว่านี้หรือไม่?
Russell Steen

ฉันอยากลองดูว่า FORTRAN และภาษาอื่น ๆ รองรับจำนวนเต็ม 64 บิตเมื่อเรายังทำงานกับระบบ 8 และ 16 บิตได้อย่างไร
โจ

@Russel Steen คุณจะแนะนำอะไรในฐานะฐานข้อมูล DB ที่แข็งแกร่งกว่านี้?
Kami

คุณยังจะต้องทำการแพ็คและแกะมันออกมา แต่ Postgres มีประเภท128 บิตแบบดั้งเดิม
ออกุสตุส

จริง ๆ แล้ว Postgres bigserial type น่าจะทำได้
ออกุสตุส

คำตอบ:


10

ฉันไม่รู้ว่าวิธีที่ดีที่สุดในการจัดเก็บคืออะไร แต่อย่างน้อยก็มีตัวเลือกที่ดีกว่าการใช้varchar(39)(หรือvarchar(40)ถ้าคุณต้องการให้ลงชื่อ) decimal(39,0)แทนที่จะใช้ จาก mysql docs :

ประเภทจุดคงที่ (ค่าแน่นอน)

ประเภท DECIMAL และ NUMERIC จะเก็บค่าตัวเลขที่แน่นอน ประเภทเหล่านี้จะใช้เมื่อมีความสำคัญในการรักษาความแม่นยำที่แน่นอนเช่นกับข้อมูลทางการเงิน ใน MySQL มีการใช้ NUMERIC เป็น DECIMAL ดังนั้นหมายเหตุเกี่ยวกับ DECIMAL ต่อไปนี้จะใช้กับ NUMERIC อย่างเท่าเทียมกัน

MySQL 5.1 เก็บค่า DECIMAL ในรูปแบบไบนารี ก่อน MySQL 5.0.3 จะถูกเก็บเป็นสตริง ดูหัวข้อ 11.18“ คณิตศาสตร์แม่นยำ”

ในการประกาศคอลัมน์ DECIMAL สามารถระบุความแม่นยำและมาตราส่วน (และปกติ) ได้ ตัวอย่างเช่น:

salary DECIMAL(5,2)

ในตัวอย่างนี้ 5 คือความแม่นยำและ 2 คือขนาด ความแม่นยำหมายถึงจำนวนตัวเลขที่มีนัยสำคัญที่เก็บไว้สำหรับค่าและมาตราส่วนแสดงถึงจำนวนของตัวเลขที่สามารถจัดเก็บได้หลังจากจุดทศนิยม

SQL มาตรฐานกำหนดให้ DECIMAL (5,2) สามารถเก็บค่าใด ๆ ด้วยตัวเลขห้าหลักและทศนิยมสองตัวดังนั้นค่าที่สามารถเก็บไว้ในคอลัมน์เงินเดือนได้ตั้งแต่ -999.99 ถึง 999.99

ใน SQL มาตรฐานไวยากรณ์ DECIMAL (M) เทียบเท่ากับ DECIMAL (M, 0) ในทำนองเดียวกันไวยากรณ์ DECIMAL เทียบเท่ากับ DECIMAL (M, 0) ซึ่งการดำเนินการได้รับอนุญาตให้ตัดสินใจว่าค่าของ M. MySQL รองรับทั้งสองรูปแบบตัวแปร DECIMAL ไวยากรณ์ ค่าเริ่มต้นของ M คือ 10

ถ้าสเกลเป็น 0 ค่า DECIMAL จะไม่มีจุดทศนิยมหรือส่วนที่เป็นเศษส่วน

จำนวนหลักสูงสุดสำหรับ DECIMAL คือ 65 แต่ช่วงจริงสำหรับคอลัมน์ DECIMAL ที่กำหนดสามารถถูก จำกัด ด้วยความแม่นยำหรือสเกลสำหรับคอลัมน์ที่กำหนด เมื่อคอลัมน์ดังกล่าวได้รับการกำหนดค่าที่มีตัวเลขมากกว่าหลังจุดทศนิยมที่ได้รับอนุญาตจากมาตราส่วนที่ระบุค่าจะถูกแปลงเป็นมาตราส่วนนั้น (พฤติกรรมที่แม่นยำนั้นเฉพาะระบบปฏิบัติการ แต่โดยทั่วไปแล้วผลกระทบจะถูกตัดให้เหลือจำนวนหลักที่อนุญาต)

มันถูกเก็บไว้บรรจุดังนั้นมันจะใช้พื้นที่น้อยกว่า varchar ( 18 ไบต์ถ้าฉันทำคณิตศาสตร์ของฉันถูกต้อง ) และฉันหวังว่าคุณจะสามารถทำคณิตศาสตร์โดยตรง แต่ฉัน ไม่เคยลองด้วยตัวเลขจำนวนมากเพื่อดูว่าเกิดอะไรขึ้น


8

ฉันพบว่าตัวเองถามคำถามนี้และจากโพสต์ทั้งหมดที่ฉันอ่านไม่เคยพบการเปรียบเทียบประสิทธิภาพใด ๆ ดังนั้นนี่คือความพยายามของฉัน

ฉันได้สร้างตารางต่อไปนี้แล้วโดยมีที่อยู่ IP สุ่ม 2,000,000 จากเครือข่ายสุ่ม 100 แห่ง

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
);

จากนั้นฉันเลือกที่อยู่ IP ทั้งหมดสำหรับแต่ละเครือข่ายและบันทึกเวลาตอบสนอง เวลาตอบสนองโดยเฉลี่ยในตาราง twobigints อยู่ที่ประมาณ 1 วินาทีในขณะที่บนโต๊ะไบนารีจะอยู่ที่ประมาณหนึ่งในร้อยของวินาที

นี่คือแบบสอบถาม

บันทึก:

X_ [สูง / ต่ำ] เป็น 64- บิตที่สำคัญที่สุดของ X

เมื่อ NETMASK_LOW เป็น 0 เงื่อนไข AND จะถูกละเว้นเนื่องจากให้ผลเป็นจริงเสมอ ไม่ส่งผลกระทบต่อประสิทธิภาพมากนัก

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

เวลาตอบกลับโดยเฉลี่ย:

เวลาตอบกลับโดยเฉลี่ย

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

ฉันเชื่อว่าตัวเลือกอื่นเท่านั้นที่จะเก็บไว้ในvarchar(39)เขตข้อมูล


2
ฉันคิดว่ามันจะใช้งานได้หากคุณต้องการเก็บข้อมูลเท่านั้น
eiefai

1
@eiefai: นั่นไม่ใช่สิ่งที่เขาถามใช่มั้ย "ฉันต้องการเก็บจำนวนเต็ม 128 บิตที่ไม่ได้ลงชื่อ"
BenV

โอ้ใช่นี่เป็นคำแนะนำที่ดีฉันเพิ่งแสดงความคิดเห็นเพื่อให้แน่ใจว่าเขาต้องการเก็บมากกว่าทำ calcs บางอย่าง
eiefai

@eiefai: โอเคฉันเข้าใจผิด คุณพูดถูกต้องคุณค่าจะต้องถูกทิ้งก่อนที่จะสามารถนำมาใช้เป็นตัวเลขได้
BenV
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.