로깅에서 지연된 상관 관계에 이르기까지 다양한 이유로 시스템에서 UUID를 잠시 사용해 왔습니다. 내가 사용하지 않은 형식은 다음과 같이 순진하지 않게 변경되었습니다.
VARCHAR(255)
VARCHAR(36)
CHAR(36)
BINARY(16)
내가 마지막 BINARY(16)
자동 증가 정수와 성능을 비교하기 시작한 마지막에 도달했을 때였습니다 . 테스트 결과는 다음과 같다,하지만 당신은 단지 요약을 원하는 경우, 그것은을 나타냅니다 INT AUTOINCREMENT
와 BINARY(16) RANDOM
(데이터베이스가 이전에 시험을 미리 입력 된) 20까지의 범위 데이터에서 동일한 성능을 가지고있다.
처음에는 기본 키로 UUID를 사용하는 것에 회의적이었습니다. 그러나 여전히 그래도 두 가지를 모두 사용할 수있는 유연한 데이터베이스를 만들 가능성이 있습니다. 많은 사람들이 둘 중 하나의 장점을 강조하지만, 두 가지 데이터 유형을 모두 사용하여 해결되는 단점은 무엇입니까?
PRIMARY INT
UNIQUE BINARY(16)
이 유형의 설정에 대한 사용 사례는 시스템 간 관계에 사용되는 고유 식별자가있는 테이블 간 관계의 기본 키가됩니다.
본질적으로 발견하려고하는 것은 두 가지 접근 방식의 효율성 차이입니다. 추가 데이터를 추가 한 후에는 거의 무시할 수있는 사중 디스크 공간 외에는 동일한 것으로 보입니다.
개요:
-- phpMyAdmin SQL Dump
-- version 4.0.10deb1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Sep 22, 2015 at 10:54 AM
-- Server version: 5.5.44-0ubuntu0.14.04.1
-- PHP Version: 5.5.29-1+deb.sury.org~trusty+3
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Database: `test`
--
-- --------------------------------------------------------
--
-- Table structure for table `with_2id`
--
CREATE TABLE `with_2id` (
`guidl` bigint(20) NOT NULL,
`guidr` bigint(20) NOT NULL,
`data` varchar(255) NOT NULL,
PRIMARY KEY (`guidl`,`guidr`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `with_guid`
--
CREATE TABLE `with_guid` (
`guid` binary(16) NOT NULL,
`data` varchar(255) NOT NULL,
PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Table structure for table `with_id`
--
CREATE TABLE `with_id` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=197687 ;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
벤치 마크 삽입 :
function benchmark_insert(PDO $pdo, $runs)
{
$data = 'Sample Data';
$insert1 = $pdo->prepare("INSERT INTO with_id (data) VALUES (:data)");
$insert1->bindParam(':data', $data);
$insert2 = $pdo->prepare("INSERT INTO with_guid (guid, data) VALUES (:guid, :data)");
$insert2->bindParam(':guid', $guid);
$insert2->bindParam(':data', $data);
$insert3 = $pdo->prepare("INSERT INTO with_2id (guidl, guidr, data) VALUES (:guidl, :guidr, :data)");
$insert3->bindParam(':guidl', $guidl);
$insert3->bindParam(':guidr', $guidr);
$insert3->bindParam(':data', $data);
$benchmark = array();
$time = time();
for ($i = 0; $i < $runs; $i++) {
$insert1->execute();
}
$benchmark[1] = 'INC ID: ' . (time() - $time);
$time = time();
for ($i = 0; $i < $runs; $i++) {
$guid = openssl_random_pseudo_bytes(16);
$insert2->execute();
}
$benchmark[2] = 'GUID: ' . (time() - $time);
$time = time();
for ($i = 0; $i < $runs; $i++) {
$guid = openssl_random_pseudo_bytes(16);
$guidl = unpack('q', substr($guid, 0, 8))[1];
$guidr = unpack('q', substr($guid, 8, 8))[1];
$insert3->execute();
}
$benchmark[3] = 'SPLIT GUID: ' . (time() - $time);
echo 'INSERTION' . PHP_EOL;
echo '=============================' . PHP_EOL;
echo $benchmark[1] . PHP_EOL;
echo $benchmark[2] . PHP_EOL;
echo $benchmark[3] . PHP_EOL . PHP_EOL;
}
벤치 마크 선택 :
function benchmark_select(PDO $pdo, $runs) {
$select1 = $pdo->prepare("SELECT * FROM with_id WHERE id = :id");
$select1->bindParam(':id', $id);
$select2 = $pdo->prepare("SELECT * FROM with_guid WHERE guid = :guid");
$select2->bindParam(':guid', $guid);
$select3 = $pdo->prepare("SELECT * FROM with_2id WHERE guidl = :guidl AND guidr = :guidr");
$select3->bindParam(':guidl', $guidl);
$select3->bindParam(':guidr', $guidr);
$keys = array();
for ($i = 0; $i < $runs; $i++) {
$kguid = openssl_random_pseudo_bytes(16);
$kguidl = unpack('q', substr($kguid, 0, 8))[1];
$kguidr = unpack('q', substr($kguid, 8, 8))[1];
$kid = mt_rand(0, $runs);
$keys[] = array(
'guid' => $kguid,
'guidl' => $kguidl,
'guidr' => $kguidr,
'id' => $kid
);
}
$benchmark = array();
$time = time();
foreach ($keys as $key) {
$id = $key['id'];
$select1->execute();
$row = $select1->fetch(PDO::FETCH_ASSOC);
}
$benchmark[1] = 'INC ID: ' . (time() - $time);
$time = time();
foreach ($keys as $key) {
$guid = $key['guid'];
$select2->execute();
$row = $select2->fetch(PDO::FETCH_ASSOC);
}
$benchmark[2] = 'GUID: ' . (time() - $time);
$time = time();
foreach ($keys as $key) {
$guidl = $key['guidl'];
$guidr = $key['guidr'];
$select3->execute();
$row = $select3->fetch(PDO::FETCH_ASSOC);
}
$benchmark[3] = 'SPLIT GUID: ' . (time() - $time);
echo 'SELECTION' . PHP_EOL;
echo '=============================' . PHP_EOL;
echo $benchmark[1] . PHP_EOL;
echo $benchmark[2] . PHP_EOL;
echo $benchmark[3] . PHP_EOL . PHP_EOL;
}
테스트 :
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
benchmark_insert($pdo, 1000);
benchmark_select($pdo, 100000);
결과 :
INSERTION
=============================
INC ID: 3
GUID: 2
SPLIT GUID: 3
SELECTION
=============================
INC ID: 5
GUID: 5
SPLIT GUID: 6
BINARY(16)
우리 둘 다 UUID를 저장하는 가장 효율적인 방법이라고 생각하지만UNIQUE
인덱스와 관련하여 간단히 일반 인덱스를 사용해야합니까? 바이트는 암호화 된 보안 RNG를 사용하여 생성되므로 임의성에 전적으로 의존하고 검사를 포기해야합니까?