基于php中的键查找值的有效方法 [英] Efficient way to look up value based on a key in php

查看:65
本文介绍了基于php中的键查找值的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找大约100,000个键/值对的列表(两个字符串,每个字符串大多为5-20个字符),我正在寻找一种有效查找给定键值的方法.

With a list of around 100,000 key/value pairs (both string, mostly around 5-20 characters each) I am looking for a way to efficiently find the value for a given key.

这需要在php网站中完成.我熟悉Java中的哈希表(这可能是我在Java中工作时可能要做的事情),但对php还是陌生的.

This needs to be done in a php website. I am familiar with hash tables in java (which is probally what I would do if working in java) but am new to php.

我正在寻找有关如何存储此列表(在文本文件或数据库中?)并搜索此列表的提示.

I am looking for tips on how I should store this list (in a text file or in a database?) and search this list.

该列表有时需要更新,但是我对查找时间最感兴趣.

The list would have to be updated occasionally but I am mostly interested in look up time.

推荐答案

您可以将其作为直接的PHP数组来完成,但如果可用,Sqlite将是您追求速度和便利性的最佳选择.

You could do it as a straight PHP array, but Sqlite is going to be your best bet for speed and convenience if it is available.

只需将所有内容存储在这样的php文件中:

Just store everything in a php file like this:

<?php
return array(
    'key1'=>'value1',
    'key2'=>'value2',
    // snip
    'key100000'=>'value100000',
);

然后您可以像这样访问它:

Then you can access it like this:

<?php
$s = microtime(true); // gets the start time for benchmarking

$data = require('data.php');
echo $data['key2'];

var_dump(microtime(true)-$s); // dumps the execution time

这不是世界上最有效的方法,但是它将起作用.我的机器需要0.1秒.

Not the most efficient thing in the world, but it's going to work. It takes 0.1 seconds on my machine.

PHP应该启用sqlite,这对于这种情况非常有用.

PHP should come with sqlite enabled, which will work great for this kind of thing.

此脚本将从头到尾为您创建一个数据库,该数据库具有与问题中描述的数据集相似的特征:

This script will create a database for you from start to finish with similar characteristics to the dataset you describe in the question:

<?php
// this will *create* data.sqlite if it does not exist. Make sure "/data" 
// is writable and *not* publicly accessible.
// the ATTR_ERRMODE bit at the end is useful as it forces PDO to throw an
// exception when you make a mistake, rather than internally storing an
// error code and waiting for you to retrieve it.
$pdo = new PDO('sqlite:'.dirname(__FILE__).'/data/data.sqlite', null, null, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

// create the table if you need to
$pdo->exec("CREATE TABLE stuff(id TEXT PRIMARY KEY, value TEXT)");

// insert the data
$stmt = $pdo->prepare('INSERT INTO stuff(id, value) VALUES(:id, :value)');
$id = null;
$value = null;

// this binds the variables by reference so you can re-use the prepared statement
$stmt->bindParam(':id', $id);
$stmt->bindParam(':value', $value);

// insert some data (in this case it's just dummy data)
for ($i=0; $i<100000; $i++) {
    $id = $i;
    $value = 'value'.$i;
    $stmt->execute();
}

然后使用值:

<?php
$s = microtime(true);

$pdo = new PDO('sqlite:'.dirname(__FILE__).'/data/data.sqlite', null, null, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

$stmt = $pdo->prepare("SELECT * FROM stuff WHERE id=:id");
$stmt->bindValue(':id', 5);
$stmt->execute();

$value = $stmt->fetchColumn(1);

var_dump($value);

// the number of seconds it took to do the lookup
var_dump(microtime(true)-$s);

这个速度更快.我的计算机上0.0009秒.

This one is waaaay faster. 0.0009 seconds on my machine.

您也可以使用MySQL代替Sqlite,但是如果它只是一个具有您描述的特征的表,则可能会过大.如果您有可用的MySQL服务器,则上面的Sqlite示例可以很好地使用MySQL.只需将实例化PDO的行更改为此:

You could also use MySQL for this instead of Sqlite, but if it's just one table with the characteristics you describe, it's probably going to be overkill. The above Sqlite example will work fine using MySQL if you have a MySQL server available to you. Just change the line that instantiates PDO to this:

$pdo = new PDO('mysql:host=your.host;dbname=your_db', 'user', 'password', array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

sqlite示例中的查询应该都可以在MySQL上正常运行,但是请注意,我尚未对此进行测试.

The queries in the sqlite example should all work fine with MySQL, but please note that I haven't tested this.

并不是说Sqlite解决方案很慢(0.0009秒!),但是这在我的机器上快了大约四倍.另外,Sqlite可能不可用,可能无法设置MySQL,等等.

Not that the Sqlite solution is slow (0.0009 seconds!), but this about four times faster on my machine. Also, Sqlite may not be available, setting up MySQL might be out of the question, etc.

在这种情况下,您也可以使用文件系统:

In this case, you can also use the file system:

<?php
$s = microtime(true); // more hack benchmarking

class FileCache
{
    protected $basePath;

    public function __construct($basePath)
    {
        $this->basePath = $basePath;
    }

    public function add($key, $value)
    {
        $path = $this->getPath($key);
        file_put_contents($path, $value);
    }

    public function get($key)
    {
        $path = $this->getPath($key);
        return file_get_contents($path);
    }

    public function getPath($key)
    {
        $split = 3;

        $key = md5($key);
        if (!is_writable($this->basePath)) {
            throw new Exception("Base path '{$this->basePath}' was not writable");
        }
        $path = array();
        for ($i=0; $i<$split; $i++) {
            $path[] = $key[$i];
        }
        $dir = $this->basePath.'/'.implode('/', $path);
        if (!file_exists($dir)) {
            mkdir($dir, 0777, true);
        }
        return $dir.'/'.substr($key, $split);
    }
}

$fc = new FileCache('/tmp/foo');

/*
// use this crap for generating a test example. it's slow to create though.
for ($i=0;$i<100000;$i++) {
    $fc->add('key'.$i, 'value'.$i);
}
//*/

echo $fc->get('key1', 'value1');

var_dump(microtime(true)-$s);

这需要0.0002秒才能在我的计算机上进行查找.这还具有无论缓存大小如何都保持合理恒定的优势.

This one takes 0.0002 seconds for a lookup on my machine. This also has the benefit of being reasonably constant regardless of the cache size.

这篇关于基于php中的键查找值的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆