Cara efisien untuk mencari nilai berdasarkan kunci di php [duplikat]

Dengan daftar sekitar 100.000 pasangan kunci/nilai (kedua string, sebagian besar masing-masing sekitar 5-20 karakter) saya mencari cara untuk menemukan nilai kunci tertentu secara efisien.

Ini perlu dilakukan di situs web php. Saya kenal dengan tabel hash di java (yang mungkin akan saya lakukan jika bekerja di java) tetapi saya baru mengenal php.

Saya mencari tip tentang bagaimana saya harus menyimpan daftar ini (dalam file teks atau database?) dan mencari daftar ini.

Daftarnya harus diperbarui sesekali tetapi saya lebih tertarik pada waktu pencarian.


person user552007    schedule 23.12.2010    source sumber


Jawaban (3)


Anda dapat melakukannya sebagai array PHP langsung, tetapi Sqlite akan menjadi pilihan terbaik Anda untuk kecepatan dan kenyamanan jika tersedia.

susunan PHP

Simpan saja semuanya dalam file php seperti ini:

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

Kemudian Anda dapat mengaksesnya seperti ini:

<?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

Bukan hal yang paling efisien di dunia, tapi ini akan berhasil. Dibutuhkan 0,1 detik di mesin saya.

Sqlite

PHP harus dilengkapi dengan sqlite yang diaktifkan, yang akan berfungsi dengan baik untuk hal semacam ini.

Skrip ini akan membuatkan database untuk Anda dari awal hingga akhir dengan karakteristik serupa dengan kumpulan data yang Anda jelaskan dalam pertanyaan:

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

Dan kemudian menggunakan nilai-nilai:

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

Yang ini jauh lebih cepat. 0,0009 detik di mesin saya.

MySQL

Anda juga bisa menggunakan MySQL untuk ini daripada Sqlite, tapi jika itu hanya satu tabel dengan karakteristik yang Anda jelaskan, itu mungkin akan berlebihan. Contoh Sqlite di atas akan berfungsi dengan baik menggunakan MySQL jika Anda memiliki server MySQL yang tersedia untuk Anda. Ubah saja baris yang membuat instance PDO menjadi ini:

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

Kueri dalam contoh sqlite seharusnya berfungsi dengan baik dengan MySQL, namun perlu diketahui bahwa saya belum mengujinya.

Mari kita menjadi sedikit gila: kegilaan sistem file

Bukan berarti solusi Sqlite lambat (0,0009 detik!), tapi ini sekitar empat kali lebih cepat di mesin saya. Selain itu, Sqlite mungkin tidak tersedia, pengaturan MySQL mungkin tidak dapat dilakukan, dll.

Dalam hal ini, Anda juga dapat menggunakan sistem file:

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

Yang ini membutuhkan 0,0002 detik untuk pencarian di mesin saya. Keuntungannya adalah cukup konstan terlepas dari ukuran cache.

person Shabbyrobe    schedule 23.12.2010

Itu tergantung pada seberapa sering Anda mengakses array Anda, pikirkan seperti ini berapa banyak pengguna yang dapat mengaksesnya pada saat yang sama. Ada banyak keuntungan menyimpannya dalam database dan di sini Anda memiliki dua opsi MySQL dan SQLite.

SQLite berfungsi lebih seperti file teks dengan dukungan SQL, Anda dapat menghemat beberapa milidetik selama kueri karena terletak dalam jangkauan aplikasi Anda, kelemahan utamanya adalah ia hanya dapat menambahkan satu catatan pada satu waktu (sama seperti file teks). Saya akan merekomendasikan SQLite untuk array dengan konten statis seperti data GEO IP, terjemahan, dll.

MySQL adalah solusi yang lebih kuat tetapi memerlukan otentikasi dan terletak di mesin terpisah.

person Nazariy    schedule 23.12.2010

Array PHP akan melakukan semua yang Anda butuhkan. Tapi bukankah data sebanyak itu harus disimpan dalam database?

http://php.net/array

person Jonah    schedule 23.12.2010