Генерация уникального идентификатора для данной строки с использованием php - PullRequest
0 голосов
/ 21 июня 2010

Я использую Zend_Cache_Core с Zend_Cache_Backend_File для кэширования результатов запросов, выполненных для модельного класса, который обращается к базе данных.

По сути, сами запросы должны формировать идентификатор, с помощью которого кешируются полученные результаты, единственная проблема в том, что они слишком длинные.Zend_Cache_Backend_File не выдает исключение, PHP не жалуется, но файл кэша не создается.

Я пришел к решению, которое вообще неэффективно, сохраняя любой выполненный запрос вместе савтоинкрементный идентификатор в отдельном файле, например:

0 - >> SELECT * FROM table 1 - >> SELECT * FROM table1, table2 2 - >> SELECT * FROM table WHERE foo = bar

Вы поняли идею;таким образом, у меня есть уникальный идентификатор для каждого запроса.Я очищаю кеш всякий раз, когда выполняется вставка, удаление или обновление.

Теперь я уверен, что вы видите потенциальное узкое место здесь, для любого теста, сохранения или выборки из кэша, два (или три, где нам нужно добавить новый идентификатор) запросов к файловой системе.Это может даже победить необходимость кеширования полностью.Так есть ли способ, которым я могу генерировать уникальный идентификатор, то есть гораздо более короткое представление, запросов в php без необходимости хранить их в файловой системе или в базе данных?

Ответы [ 2 ]

1 голос
/ 21 июня 2010

Строки произвольно длинные, поэтому, очевидно, невозможно создать идентификатор фиксированного размера, который может представлять любую произвольную входную строку без дублирования. Однако для целей кэширования вы обычно можете выбрать простое «достаточно хорошее» решение, которое уменьшает количество конфликтов до приемлемого уровня.

Например, вы можете просто использовать MD5, который вызовет столкновение только в 1 в 2 128 случаях. Если вы по-прежнему беспокоитесь о коллизиях (и, вероятно, так должно быть, просто для безопасности), вы можете сохранить запрос и результат в «значении» кэша и проверить, когда получите значение назад, что это на самом деле запрос, который вы искали.

В качестве быстрого примера (мой PHP немного ржавый, но, надеюсь, вы поняли):

$query = "SELECT * FROM ...";

$key = "hash-" + hash("md5", $query);
$result = $cache->load($key);
if ($result == null || $result[0] != $query) {
    // object wasn't in cache, do the real fetch and store it
    $result = $db->execute($query); // etc

    $result = array($query, $result);
    $cache->save($result, $key);
}

// the result is now in $result[1] (the original query is in $result[0])
0 голосов
/ 21 июня 2010

MD5 !!

Md5 генерирует строку длиной 32, которая, кажется, работает нормально, файлы кэша создаются (с именами файлов длиной примерно 47), поэтому создается впечатление, что операционная система не отклоняет их.

//returns id for a given query
function getCacheId($query) {
    return md5($query);
}

И это все! Но есть проблема использования коллизий, и я думаю, что соление хеша md5 (возможно, с именем таблицы) должно сделать его более устойчивым.

//returns id for a given query
function getCacheId($query, $table) {
    return md5($table . $query);
}

Если кому-то нужен полный код для того, как я реализовал кэширование результатов, просто оставьте комментарий, и я буду рад опубликовать его.

...