मैं अपने सिस्टम में UUIDs का उपयोग कुछ समय से कई कारणों से कर रहा हूँ, जिनमें लॉगिंग से लेकर विलंबित सहसंबंध तक शामिल हैं। मेरे द्वारा उपयोग किए जाने के बाद मैंने जिन स्वरूपों का उपयोग किया वह कम भोले बन गए:
VARCHAR(255)
VARCHAR(36)
CHAR(36)
BINARY(16)
यह तब था जब मैं अंतिम एक पर पहुंचा BINARY(16)
कि मैंने बुनियादी ऑटो-इंक्रीमेंट पूर्णांक के साथ प्रदर्शन की तुलना करना शुरू कर दिया। परीक्षण और परिणाम नीचे दिखाए गए हैं, लेकिन यदि आप केवल सारांश चाहते हैं, तो यह इंगित करता है कि INT AUTOINCREMENT
और BINARY(16) RANDOM
200,000 तक डेटा रेंज पर समान प्रदर्शन है (डेटाबेस परीक्षणों से पहले पूर्व-आबादी था)।
मैं प्राथमिक कुंजी के रूप में यूयूआईडी का उपयोग करने के लिए शुरू में संदेह था, और वास्तव में मैं अभी भी हूं, हालांकि मैं एक लचीला डेटाबेस बनाने के लिए यहां संभावित देखता हूं जो दोनों का उपयोग कर सकता है। जबकि कई लोग या तो फायदे पर जोर देते हैं, दोनों डेटा प्रकारों के उपयोग से क्या नुकसान हैं?
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)
मुझे लगता है कि हम दोनों सहमत हैं कि यूयूआईडी स्टोर करने का सबसे कुशल तरीका है, लेकिनUNIQUE
सूचकांक के बारे में , क्या मुझे बस एक नियमित सूचकांक का उपयोग करना चाहिए? बाइट्स क्रिप्टोग्राफिक रूप से सुरक्षित आरएनजी का उपयोग करके उत्पन्न होते हैं, इसलिए क्या मैं पूरी तरह से यादृच्छिकता पर निर्भर करूंगा, और चेक वापस कर दूंगा?