【问题标题】:Riak: Getting multiple items quicklyRiak:快速获取多个项目
【发布时间】:2023-03-19 22:09:01
【问题描述】:

假设我在 PHP 中有这个数组。

$ids = [
    246,
    8362,
    5241,
    2586,
    6548,
    9372,
    28504,
    14,
    5729
];

这些数组元素对应于存储桶“articles”中的项目,有时这个数组可能有 1000 个元素深。

目前,我正在循环遍历所有这些数据并逐个提取数据。

$articles = [];
foreach($ids as $id)
{
    $articles[] = Riak::get("articles.$id");
}

当 id 列表变得很长时,这比我愿意花费的时间要多。

有没有更快的方法从 Riak 存储桶中提取项目列表?我环顾了一下,map-reduce 很有用,但显然比我使用顺序 GET 请求节省的开销更多。

【问题讨论】:

    标签: php riak


    【解决方案1】:

    不幸的是,有效地从 Riak 获取大量记录很困难,因为它们分布在整个集群中并且必须单独检索。一些客户端库最近获得了对客户端多获取的支持,它允许使用多个连接并行获取对象,但我认为这还没有到达 PHP 客户端。

    使用 mapreduce 执行此操作将减少对数据库的调用次数,但不会导致仲裁读取,因为它仅查询覆盖的分区集。然而,Mapreduce 是一种相当广泛的数据查询方式,它的扩展性或性能几乎不及直接键访问。

    如果这是您需要执行的常见操作,则可能表明您的数据模型过于规范化,您可能需要去规范化以使其更好地支持您的应用程序及其访问模式。

    究竟如何最好地做到这一点需要了解您的数据以及您的访问和查询模式。一种方法可能是将多篇文章存储在单个对象中,该对象具有基于例如的已知且可预测的键。固定范围的文章 ID。这将使文章的检索更加高效,因为需要读取的对象显着减少,但在更新和插入时可能会增加一些复杂性。

    另一种选择是通过复制数据来反规范化。如果你例如只需要文章中的一些信息,您可以将这些数据存储在专门用于有效服务这些查询的单独对象中。

    在 Riak 中,通常更好地检索具有比您需要的更多信息的更大对象并在应用程序级别进行过滤,而不是尝试从数据库中获取您需要的准确记录。

    【讨论】:

    • 我最终仔细研究了我们是如何存储数据的。对数据进行反规范化最终成为更好的方法。有些数据可能不像我们希望的那样是最新的,但它对我们来说并不像尽快检索数据那么重要。谢谢你的回答,正是我需要的。
    【解决方案2】:

    基于https://github.com/basho/riak-php-client PHP 示例:

    /**
         * Retrieve JSON-encoded objects from Riak.
         * @param  array(int) $keys - List of the key.
         * @return RiakObjects
         */
        public function multiGet($keys) {
            if (!$keys || !count($keys))
                return array();
            $query = null;
            foreach ($keys as $key) {
                if ($query) {
                    $query->add($this->getBucketName(), $key);
                } else {
                    $query = $this->riak->add($this->getBucketName(), $key);
                }
            }
            $results = $query->map(('function(riakObject){return [{"key":riakObject.key, "document":riakObject.values}];}'))->run();
            if (!$results || !count($results)) {
                return array();
            }
    
            $objects = array();
            foreach ($results as $data) {
                if (isset($data->key) && isset($data->document[0]->data) && !empty($data->document[0]->data)) {
                    $object = json_decode($data->document[0]->data, true);
                    if ($object) {
                        $objects[$data->key] = $object;
                    }
                }
            }
            return $objects;
        }
    

    【讨论】:

    • +1 用于将它与一种方法连接起来,该方法可以满足我的需求,但不幸的是,它的执行速度仍然太慢,我不喜欢。我最终以不同的格式存储数据。我知道这是人们正在寻找的相当普遍的东西,我希望这对其他人有用。
    • 此方法使用 mapreduce 检索多个对象。值得指出的是,这是一个相当昂贵的操作,并且具有不会导致仲裁读取的缺点(将其视为 R=1 和 notfound_ok=true 的读取)。
    猜你喜欢
    • 2015-01-28
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    相关资源
    最近更新 更多