2010-06-21 86 views
0

我使用Zend_Cache_Core和Zend_Cache_Backend_File来缓存为访问数据库的模型类执行的查询结果。使用php为给定字符串生成一个唯一的ID

基本上查询本身应该形成缓存获得结果的id,唯一的问题是,它们太长。 Zend_Cache_Backend_File不会引发异常,PHP不会发出抱怨,但不会创建缓存文件。

,我想出了一个解决方案,它是没有效率可言,与自动增量ID一起在一个单独的文件中存储任何执行的查询,像这样:

0 - >> SELECT * FROM表 1- >> SELECT * FROM table1,table2 2 - >> SELECT * FROM表where where foo = bar

你明白了;这种方式我有每个查询唯一的ID。每当插入,删除或更新完成时,我都会清理缓存。

现在,我敢肯定,你在这里看到了潜在的瓶颈,对于任何测试,保存或从缓存中两个(或三个,在这里我们需要添加一个新的ID)请求对文件系统进行读取。这甚至可能无法将全部缓存。那么有没有一种方法可以生成一个唯一的ID,即更短的表示形式,而不必将它们存储在文件系统或数据库中?

回答

1

字符串是任意长的,所以显然它是不可能创建一个固定大小的标识符,可以表示任何任意输入字符串,而不会重复。但是,为了缓存目的,通常可以避免使用简单“足够好”的解决方案,并将冲突减少到可接受的水平。

例如,您可以简单地使用MD5,该MD5仅会在产生1个冲突的情况下产生冲突。如果您仍然担心碰撞(为了安全起见,您可能应该是这样),您可以将查询的结果存储在缓存的“值”中,并检查何时将值返回为实际值您正在查找的查询。

作为一个简单的例子(我的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

Thanx!我现在正在尝试。两个问题。我认为哈希反复给出相同的输入字符串时应该产生相同的结果。这是不正确的? md5 hash的长度是多少,因为我认为由于结果文件名的长度,查询本身被操作系统的id拒绝了? 谢谢,虽然我正在尝试,但会有一些地方需要重构,所以需要一段时间。我知道我必须缓存查询以及结果,但无法弄清楚! – Joey 2010-06-21 02:16:05

+0

我已经在前面的评论中找出了两个问题的答案,并且我已经在下面发布了答案。但我仍然不确定与md5哈希碰撞,有人请向我解释。 – Joey 2010-06-21 02:57:08

+0

@Joey:使用具有相同字符串的MD5将始终生成相同的输出,但问题在于2 * 128的概率有两个*不同*字符串也会生成相同的输出。所以有可能(尽管不太可能)两个不同的查询会散列到相同的MD5密钥。这就是为什么我在那里添加额外支票:确保不会发生。 – 2010-06-21 04:13:27

0

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); 
} 

如果有人想要我完成结果缓存的完整代码,只需发表评论,我会很乐意发布它。