【问题标题】:PHP: how to index multiple keys in associative array?PHP:如何索引关联数组中的多个键?
【发布时间】:2015-03-19 19:28:12
【问题描述】:

我将使用 PHP 构建一个“简单”的 RESTful Web 服务。我将提供 API 来访问我在 Web 服务器上收集的一些数据(通过 JSON)。主数据表对于公共 API 方法将是只读的,并且将由单例私有方法定期写入。用户将能够将一些数据写入私有表。

我想避免——如果可能的话——增加处理数据库的复杂性(甚至 SQLite 也不行);所以,我打算在磁盘上的文件上序列化我的数据,并在调用 PHP 脚本时在内存中反序列化它们。

将每个PHP实例的全部数据加载到内存中不会对Web服务器造成太大的负担(我希望)...... (数字是这些:主数据表大小计划最大为100k 条记录,每条记录的最大记录大小为 1k 字节,因此数据大小的最大可能大小为 100MB,通常大小为 10MB;最大并发用户数永远不会高于 100;这些数字是由设计,不可能变大)。

问题是:我可以使用 PHP 关联数组对多个键执行查询吗?

一个例子:这是我简化的主要数据结构:

<?php
    $data = [
        "1" => [
            "name" => "Alice",
            "zip" => "12345",
            "many" => "A",
            "other" => "B",
            "fields" => "C",
        ],
        "2" => [
            "name" => "Bob",
            "zip" => "67890",
            "many" => "X",
            "other" => "Y",
            "fields" => "Z",
        ],
        // ...
    ];
?>

当然,要通过主键访问记录,我应该这样做:

$key = "12345";
$record = $data[$key];

但是,如果我想(有效地,即避免顺序扫描......)通过不同的键访问一个或多个记录,比如“zip”,该怎么办?当然,这些键可能包含重复的值。我想出的唯一解决方案是为每个辅助键构建一个新数组以“索引”,并将其与主数据表一起序列化...

例如:

$zip_idx = [
    "12345" => [ "1", "355", "99999", ],
    "67890" => [ "2", "732", ],
    // ...
];

然后:

$zip = "67890";
$records = $zip_idx[$zip];

所以:
您是否发现此设计存在任何问题、不一致或缺乏灵活性?
您能提出任何更智能或更紧凑的解决方案吗?
您有什么考虑或反对吗?

【问题讨论】:

    标签: php multidimensional-array indexing


    【解决方案1】:

    我不会为其他“索引”创建任何进一步的数组。

    只需创建一个处理查询的好类。对 zip 的查询可能如下所示

    class Data{
    
        protected $data;
    
        public function getByZip($zip){
            return array_filter($this->getData(),function($item)use($zip){
                 if($item['zip'] == $zip) return true;
                 return false;
            });
        }
    
        public function setData($data){
            $this->data = $data;
        }
    
        public function getData($data){
            return $this->data;
        }
    }
    
    $dataArray = [
        "1" => [
            "name" => "Alice",
            "zip" => "12345",
            "many" => "A",
            "other" => "B",
            "fields" => "C",
        ],
        "2" => [
            "name" => "Bob",
            "zip" => "67890",
            "many" => "X",
            "other" => "Y",
            "fields" => "Z",
        ],
        // ...
    ];
    
    $data = new Data();
    
    $data->setData($dataArray);
    
    $result = $data->getByZip(12345);
    

    您也可以使用数组中的用户标识并以这种方式查询。

    问候

    编辑:关于你的表现问题-> 正常情况下,您将数据库用于可以达到 100MB 的数据。 原因是 - 如果您使用数组文件数据库 - 必须将 100MB 的整个文件读入内存。这不是什么大问题,但大多数提供商为您的应用程序使用 128MB 的最大内存限制,这可能会导致问题。

    【讨论】:

    • 谢谢...但是,来自 php array_filter 的文档 (php.net/manual/en/function.array-filter.php):“迭代数组中的 每个 值”... :-( 恐怕它不会那么有效... :-)
    • 它非常高效 - php 数组迭代比任何数据库查询都快。 - 如果您想测试性能,只需在迭代开始/结束时进行 microtime() 回显以检查所需时间 - 您需要读取文件的时间将成为瓶颈
    • 嗯...我会尽快尝试您的解决方案... :-)
    • 为了提高效率,你应该使用 php serialize() 将数组写入文件。
    • 你的代码有一个小错误:你在{之前关闭了array_filter(括号,但是它应该在}之后关闭......顺便说一句,它非常有效,我会的实现基于array_filter的解决方案...谢谢...
    猜你喜欢
    • 2012-03-18
    • 2015-08-18
    • 2011-05-04
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 2021-05-05
    • 2014-04-20
    • 2020-04-16
    相关资源
    最近更新 更多