MySQL에서 128비트 숫자를 한 열에 저장하는 방법?
IP 주소를 문자열이 아닌 숫자로 저장하기 위해 테이블을 변경합니다.32비트 주소가 정수 열에 들어갈 수 있는 IPv4에서는 간단합니다.그러나 IPv6 주소는 128비트입니다.
MySQL 문서에는 64비트("bigint")까지의 숫자 유형만 표시됩니다.
IPv6의 경우 char/varchar를 사용해야 합니까? (IPv4와 IPv6의 경우 동일한 열을 사용하는 것이 이상적이므로 이 작업을 하지 않는 것이 좋습니다.)
두 개의 bigint 열을 사용하는 것보다 더 좋은 것이 있습니까?주소를 사용할 때마다 값을 상위/하위/64로 나눌 필요가 없기를 바랍니다.
MariaDB 5.1을 사용하고 있습니다. MySQL의 최신 버전에서 더 나은 솔루션이 있다면 즉시 도움이 되지는 않지만 알아두는 것이 좋습니다.
[편집] 이 작업을 수행하는 가장 좋은 방법에 대한 권장 사항을 찾고 있습니다. (기존 문자열 표현을 포함하여) 다양한 방법이 있는 것은 분명하지만, (성능 측면에서) 가장 좋은 방법은 무엇입니까?(즉, 누군가가 이미 분석을 완료한 경우, 분석을 수행하는 데 절약할 수 있을 것입니다. 또는 분명한 내용을 놓치고 있는 경우, 이를 알아두면 좋을 것입니다.)
저는 이 질문을 하는 제 자신을 발견했고 제가 읽은 모든 게시물에서 성능 비교를 찾을 수 없었습니다.자, 제 시도는 이렇습니다.
저는 100개의 임의 네트워크에서 2,000,000개의 임의 IP 주소로 채워진 다음 표를 만들었습니다.
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 주소를 선택하고 응답 시간을 기록합니다.두 빅인츠 테이블의 평균 응답 시간은 약 1초인 반면 이진 테이블의 응답 시간은 약 100분의 1초입니다.
문의 내용은 다음과 같습니다.
참고:
X_[HIGH/LOW]는 X의 64비트 중 가장/가장 의미가 없습니다.
NETMASK_LOW가 0일 때 AND 조건은 항상 true이므로 생략됩니다.성능에 큰 영향을 주지 않습니다.
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
저는 항상 문자열이나 두 개의 64비트 정수를 사용했습니다.기록만 하고 싶은 경우는 전자, 어떤 네트워크에 어떤 주소가 포함되어 있는지 계산을 해야 하는 경우는 후자, 어떤 네트워크에 어떤 주소가 포함되어 있는지, 심지어 두 네트워크가 중복되어 있는지 계산을 해야 하는 경우는 후자입니다.
정수로 저장할 때는 실제로 두 개의 64비트 숫자로 나누는 것이 유일한 방법입니다.이렇게 하면 비교가 더 번거롭기 때문에 IP가 특정 네트워크에 속하는지 수치 계산이 필요하지 않다면 이 작업을 수행하지 않을 것입니다.
데이터 조회 수에 따라 IPv6 주소를 문자열에 저장하는 성능은 크게 신경 쓰지 않습니다.일반적으로 데이터가 거의 없거나 데이터가 거의 없습니다.네, 저장 및 조회는 숫자보다 효율성이 떨어지지만 이메일 주소, 사용자 이름 또는 사용자 이름을 저장하는 것보다 훨씬 더 고통스럽지는 않습니다.
그리고 문자열 필드에 IPv4와 IPv6를 섞을 수 없는 이유는 무엇입니까?그것들은 하나를 회수할 때 쉽게 구별할 수 있습니다.가능한 값의 범위가 겹치지 않습니다.
간단히 말해서, 중복을 확인할 때 숫자를 사용하고, 다른 곳에서는 문자열을 사용합니다.문자열의 비효율성은 사용 편의성과 비교해 볼 때 무관합니다.
인용하자면: "이진법(64)을 고려했습니까?"
언급URL : https://stackoverflow.com/questions/4444771/how-to-store-a-128-bit-number-in-a-single-column-in-mysql
'programing' 카테고리의 다른 글
리눅스에서 c의 bool type을 사용하기 위해 어떤 헤더 파일을 포함합니까? (0) | 2023.09.21 |
---|---|
WordPress 및 BuddyPress 스팸 차단 (0) | 2023.09.21 |
gcc로 C를 컴파일할 때 전처리된 .i 파일에서 숫자의 의미는 무엇입니까? (0) | 2023.09.21 |
j클릭시 이벤트를 동적으로 추가된 HTML 요소에 바인딩하는 방법 쿼리 (0) | 2023.09.21 |
깃 푸시가 "빠른 방향으로 이동하지 않음"을 거부했습니다. (0) | 2023.09.21 |