MongoDB 索引扫描方式及效率对比研究

阅读时长 10 分钟读完

前言

索引在数据库中的作用是不言自明的,它可以使数据查询更加高效,也可以避免全表扫描等低效操作。在 MongoDB 中,索引同样也具有重要的作用,在一些高效查询和大数据量的应用场景中更是不可或缺的。但是,在实际开发中,如何正确使用索引并发挥它的最大威力,则需要我们了解索引扫描方式及其效率,才能在应用中得心应手地使用它。

索引扫描方式

在 MongoDB 中,索引扫描方式可以分为两种:全索引扫描和索引范围扫描。它们的优点和缺点如下:

全索引扫描

全索引扫描是 MongoDB 中最简单、最基础的扫描方式。其操作方式是按照索引字段的顺序对所有索引条目逐一扫描,当检索到需要的数据时就返回,扫描到集合末尾则结束。由于它不需要对数据进行排序,因此速度较快。但是,当数据量大时,随着扫描次数的增加,查询速度会明显下降。

索引范围扫描

索引范围扫描是通过索引范围过滤进行数据扫描,只有满足条件的数据才会被返回。它基本上适用于所有的查询操作,速度相对全索引扫描较慢。但是,在查询大数据量的集合时,它却是最有效的扫描方式。

索引效率对比

为了更加深入了解索引扫描方式的效率和效果,我们可以通过实际的代码实验来对比它们的效率。

假设有一个用户数据库,其中保存了 100 万条数据。首先我们看一下全索引扫描的代码实现:

查询的返回结果中包含了执行时间、扫描行数、扫描文档数、查找行数等详细统计信息。假设查询的结果为:

-- -------------------- ---- -------
-
    -------------- - -
        ---------------- - --
        ----------- - ----------------
        ---------------- - ------
        ------------- - -

        --
        ------------- - -
            ------- - -----------
            ----------- - ---------
        --
        --------------- - - -
    --
    ---------------- - -
        ------------------ - -----
        ----------- - --------
        --------------------- - ------
        ------------------- - --
        ------------------- - --------
        ----------------- - -
            ------- - -----------
            ----------- - --------
            ----------------------------- - -----
            ------- - --------
            ---------- - --------
            ---------- - --
            ----------- - --
            ----------- - -----
            -------------- - -----
            ------- - --
            ------------- - --
            ----------- - ----------
            -------------- - -------
        -
    --
    ------------ - -
        --------- - --------
        ------------ - -------------------------------------------
        --------- - - --
        ----------- - ----------
    --
    ---- - ---
-

可以看到,在全索引扫描的情况下,查询耗时为 10654ms,扫描文档数为 1000000

接下来是使用索引范围扫描的代码实现。假设我们需要查询年龄在 20 到 30 岁之间的用户:

查询结果为:

-- -------------------- ---- -------
-
    -------------- - -
        ---------------- - --
        ----------- - ----------------
        ---------------- - ------
        ------------- - -
            ------ - -
                -
                    ----- - -
                        ------ - --
                    -
                --
                -
                    ----- - -
                        ----- - --
                    -
                -
            -
        --
        ------------- - -
            ------- - --------
            ------------ - -
                ------- - ---------
                ------------ - -
                    ----- - -
                --
                ----------- - ------
                ------------ - ------
                --------------- - -
                    ----- - - -
                --
                ---------- - ------
                ---------- - ------
                ----------- - ------
                -------------- - --
                ----------- - ----------
                ------------- - -
                    ----- - -
                        ------- ------
                    -
                -
            -
        --
        --------------- - - -
    --
    ---------------- - -
        ------------------ - -----
        ----------- - -------
        --------------------- - -----
        ------------------- - -------
        ------------------- - -------
        ----------------- - -
            ------- - --------
            ----------- - -------
            ----------------------------- - ----
            ------- - -------
            ---------- - -------
            ---------- - --
            ----------- - --
            ----------- - -----
            -------------- - -----
            ------- - --
            ------------- - --
            -------------- - -------
            --------------- - --
            ------------ - -
                ------- - ---------
                ----------- - -------
                ----------------------------- - ----
                ------- - -------
                ---------- - -------
                ---------- - --
                ----------- - --
                ----------- - -----
                -------------- - -----
                ------- - --
                ------------- - --
                ------------ - -
                    ----- - -
                --
                ----------- - ------
                ------------ - ------
                --------------- - -
                    ----- - - -
                --
                ---------- - ------
                ---------- - ------
                ----------- - ------
                -------------- - --
                ----------- - ----------
                ------------- - -
                    ----- - -
                        ------- ------
                    -
                --
                -------------- - ------
            -
        -
    --
    ------------ - -
        --------- - --------
        ------------ - -------------------------------------------
        --------- - - --
        ----------- - ----------
    --
    ---- - ---
-

可以看到,在使用索引范围扫描的情况下,查询耗时仅为 1251ms,扫描文档数为 100000,查询速度比全索引扫描快了很多。

总结和指导意义

从以上的实验中我们可以看到,在大数据量的情况下,使用索引范围扫描是比全索引扫描更加高效的,因为它只扫描了包含所需数据的文档,而不需要扫描整个集合。在实际使用中,我们应该根据业务需求和数据量大小来选择合适的索引扫描方式,以达到最优效果。

此外,在设置索引时也需要注意一些细节,例如选择合适的索引字段、建立复合索引等。在查询时,也应该避免使用 $exists$regex 等操作符,以减少不必要的数据扫描。

综上所述,正确使用索引扫描方式可以显著提高 MongoDB 数据库的查询效率和程序性能,对于前端开发人员而言具有十分重要的学习和指导意义。

参考资料:

  • MongoDB 官方文档
  • 《MongoDB 实战》

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64faf5daf6b2d6eab31b93fb

纠错
反馈