I need to store 1000s (and possibly soon 100,000s maybe even millions) of unique random strings of 12 characters in a database. Every time I have to generate a new code (actually done in batches of 10,000+s) I need to compare it against the existing database to ensure there will be no duplicates -- but also when a code is "redeemed" by a user, I need to ensure it exists.
Both of these tasks are likely to be very slow, so I wish to make them as streamlined as possible. To begin with I've ensured that the strings are stored in BINARY format on the DB with an INDEX on them. This is apparently quicker than CHAR, VARCHAR and VARBINARY.
I was thinking of trying to do further improvements, and I came up with this simple idea: Storing the first character as a TINYINT in an indexed column, and comparing that first -- thus hopefully finding matching records faster.
For example:
public function getFirstCharAsNum($code) {
$firstChar = substr($code, 0);
$firstCharHex = bin2hex($firstChar);
$prefix = hexdec($firstCharHex);
return $prefix;
}
public function isDuplicate($generatedCode) {
$result = false;
$params["code"] = $generatedCode;
$params["prefix"] = getFirstCharAsNum($generatedCode);
$STH = $this->_db->prepare("SELECT count(*) FROM codes
WHERE prefix = :prefix AND code = :code;");
try {
$result = $STH->execute($params);
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
$result = $STH->fetch(PDO::FETCH_COLUMN);
if($result) {
return true;
} else {
return false;
}
}
The idea is that it will only attempt the second part of the AND operation if it finds a match, and searching through TINYINTs should be a lot quicker than a whole BINARY(12) column.
Is this actually quicker? Or is adding an additional lookup going to slow me down?
Thanks.
Storing the first character as a TINYINT and comparing that first, thus hopefully finding matching records faster.MySQL will do the job. (That's why you created an index)