【问题标题】:mongoDB index strategyMongoDB索引策略
【发布时间】:2013-07-25 03:15:59
【问题描述】:

我有一个名为 Post 的集合。我有一个映射系统,它始终确保每个文档都有这些字段:

  • id (int)
  • 目标(字符串)
  • 类型(字符串)
  • user_id
  • client_id
  • 已更新(字符串,11 个整数时间戳)
  • 已创建(字符串,11 个 int 时间戳)
  • 启用(布尔)

访问此集合以在 API 架构中输出。

所以一些典型的请求可能是:

/post?type=image&user_id=2
/post?updated=35234423&order_by=client_id
/post?enabled=true&order_by=id

没有 100% 保证某些字段会进入查找或排序字段。

最近当表达到 8GB 数据时,我开始收到此错误:

"localhost:27017: too much data for sort() with no index. add an index or specify a smaller limit"

我查看了 Mongo 索引的文档,发现很难理解它是否以与 MySQL 索引相同的方式工作。

我在索引中发现的一些线程:MongoDB - too much data for sort() with no index error 似乎建议使用特定的排序字段来确保索引被命中。显然,当我的很多过滤和排序是可选的时,我不能这样做。

就我是否应该索引表中的所有字段而言,谁能提出一个可靠的解决方案?


感谢大家的反馈,我已经开始构建自动索引功能了:

public function get() {

        $indices['Post'] = array(
            'fields' =>
                array(
                    'id'                => array('unique' => true, 'dropDups' => true, 'background' => true),
                    'client_id'         => array('dropDups' => true, 'background' => true),
                    'image_id'          => array('dropDups' => true, 'background' => true),
                    'user_id'           => array('dropDups' => true, 'background' => true),
                    'publish_target'    => array('dropDups' => true, 'background' => true),
                    'type'              => array('dropDups' => true, 'background' => true),
                    'status'            => array('dropDups' => true, 'background' => true),
                    'text'              => array('background' => true)
                )
        );

        foreach ($indices as $key => $index) {

            /* set the collection */
            $collection = $this->mongoDB->{$key};

            /* delete the indexes */
            $collection->deleteIndexes();

            /* loop the fields and add the index */
            foreach ($index['fields'] as $subKey => $data) {
                $collection->ensureIndex($subKey, array_merge($data, array('name' => $subKey)));
            }
        }
        /* return the list */
        return $indices;
    }

【问题讨论】:

  • 您能分享您的疑问吗?对分析有帮助吗?
  • @user10 如果您向下看大约一半,他会分享他的 quireies 示例;这就是jira.mongodb.org/browse/SERVER-3071 真正有用的地方

标签: php mongodb indexing


【解决方案1】:

您应该预先知道什么样的查询将访问服务器。否则,您将无法进行任何优化,并且可能会遇到像现在这样的排序问题。

如果您说用户可以按您拥有的 9 个字段中的任何一个进行排序,您将需要为每个字段创建一个索引。但是您需要记住,有时创建复合索引更有意义,因为它可以防止以下问题:

/post?updated=35234423&order_by=client_id

只能通过设置索引来完成:

{ updated: 1, client_id: 1 }

只有当索引中的所有左侧字段都是查询的一部分时,才能使用 MongoDB 中的索引。

所以:{ updated: 1, client_id: 1 } 最适合:

  • find( { 'updated' : 1 } );
  • find( { 'updated' : 1, 'client_id' : 1 } );
  • find( { 'updated' : 1 } ).sort( { 'client_id' : 1 } );

但不适用于:

  • find( { 'client_id' : 1 } );
  • find( { 'client_id' : 1 } ).sort( { 'updated' : 1 } );

为了减少数据量并防止出现错误消息,您还可以在每个查询中额外添加limit()。对于 8MB 的结果,我怀疑你的 UI 是否能显示这么多结果,所以使用 limit() 可能有意义。

【讨论】:

  • 谢谢。所以我可以根据常见请求构建大约 25 个索引,但这会更慢吗?
  • 插入/更新/删除等时,更多索引将花费更多时间。您可能需要重新考虑架构设计。
【解决方案2】:

不幸的是,我想不出一个真正好的解决方案来解决这种动态性质的索引,但是这个 JIRA https://jira.mongodb.org/browse/SERVER-3071 真的会帮助你。

我建议你看那个 JIRA 票。

【讨论】:

  • 感谢分享,我会留意的。
  • 索引交集在这里没有帮助,因为您至少仍然需要每个字段的索引。
  • @Derick 确实,但它比 atm 更有帮助,因为 mongodb 每个查询只能使用一个索引,通过交叉,您可以在每个字段上放置一个索引并获取索引使用情况,就像大多数 SQL 技术人员一样跨度>
猜你喜欢
  • 2023-03-23
  • 2021-02-07
  • 2012-02-29
  • 2012-12-22
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多