将 MySQL 结果转换为 JSON 的效率

Posted

技术标签:

【中文标题】将 MySQL 结果转换为 JSON 的效率【英文标题】:Efficiency of converting MySQL result to JSON 【发布时间】:2021-12-24 03:41:32 【问题描述】:

我使用 mysql 后端来存储我们在单页 Angular 应用程序中使用的数据。我们从服务器发送数据并将其存储在 Chrome 内的 IndexedDB 中。我们有相当多的信息表,但特别是有一个包含大约 20k 个条目和接近 300 个字段的表。当我们最初开发平台时,我们运行一个标准的 SQL 查询,然后我们迭代结果以构建一个 JSON 语句来返回。这个过程大约需要 35 秒,所以我们一直在寻求改进。从那以后,我一直在测试 MySQL 中更多特定的 JSON 工具,比如 json_array 和 json_arrayagg。我发现我已经从一个迭代过程很慢的非常快的 select 语句变成了一个不需要迭代的非常慢的 select 语句。总而言之,它所花费的时间没有任何改进。我可以使用更有效的流程来加快速度吗?作为参考,迭代是在 php 中完成的,以防那里可以使用的东西。

好的,编辑以解决一些 cmets。我们正在向客户提供这么多的数据。我们实际上有几个这种大小的表,我们在前端使用 ag-grid,以便用户可以过滤、排序、分组等。所以我们在登录时在本地加载所有数据,并在初始加载后提供一个快速的环境。初始负载是我希望改进的。对于更多的上下文,这些表之一是产品数据库。我们的用户将进入数据库,并可以按任何可用字段进行过滤。筛选依据的选项由网格中已有的数据生成。这只是一个例子,但长话短说,我们需要本地数据。

我通过记录 sql 语句周围的时间戳以及处理 sql 结果的 while 循环之前和之后来测量时间。

在创建 JSON 后返回的时间很短(几秒钟)。

我们实际上是根据运行它的模块动态构建 sql 语句,但作为参考,这里是 select 的构建方式。大模块显然会列出每个字段:

$select = " SELECT json_objectagg(json_object(
                 'docType' VALUE 'EXOAD_BidGroup',
                 'date_modified' VALUE exoad_bidgroup.date_modified ABSENT ON NULL,
                 'name' VALUE exoad_bidgroup.name ABSENT ON NULL,
                 'deleted' VALUE exoad_bidgroup.deleted ABSENT ON NULL,
                 'id' VALUE exoad_bidgroup.id ABSENT ON NULL,
                 '_id' VALUE exoad_bidgroup._id ABSENT ON NULL,
                 'isChanged' VALUE '0')) ";

最初的过程是一个基本的选择语句,然后我们使用以下内容对结果进行迭代,以在返回 JSON 之前拼凑起来:

while ($row = $GLOBALS['db']->fetchByAssoc($dbResult)) 
                $id                        = $row['id'];
                $singleResult              = array();
                $singleResult['docType']   = $module;
                $singleResult['_id']       = $row['id'];
                $singleResult['isChanged'] = 0;
                $parentKeyValue            = '';
                if ($isHierarchical == 'Yes') 
                    if (isset($row[$parentModuleKey]) && $row[$parentModuleKey] != '')
                        $parentKeyValue = $row[$parentModuleKey];
                     else 
                        continue;
                    
                
                foreach ($row as $key => $value) 
                    if ($value !== null && trim($value) <> '' && $key !== 'user_hash')  //put this in tenant utils
                        $singleResult[$key] = html_entity_decode($value, ENT_QUOTES);
                    
                

                $result_count++;
                if ($isHierarchical == 'Yes' && $parentKeyValue != '') 
                    if (!isset($output_list[$module . '-' . $parentKeyValue])) 
                        $GLOBALS['log']->info('hier module key -->> ' . $module . '-' . $parentKeyValue);
                        $output_list[$module . '-' . $parentKeyValue] = array();
                    
                    $output_list[$module . '-' . $parentKeyValue][$id] = $singleResult;
                 else 
                    $output_list[$id] = $singleResult;
                
            

如果我可以提供任何其他详细信息,请告诉我。

另一个编辑...

时间肯定是在 while 语句中的 foreach 循环中花费的。我没有确切的数字,但如果没有那个 foreach,整个过程将下降到几秒钟。但是......这就是将数据格式化为 JSON 的方式,因此任何关于加速该部分的想法都是我正在寻找的。我的猜测是它不存在,但如果有一些 php 函数可以获取每个结果行并将数据转换为 json 而无需遍历每个字段,那就太好了。

【问题讨论】:

您正在向客户端交付价值 20,000 行 * 300 列的 JSON? 您是仅测量 JSON 的生成,还是同时测量交付?您的 MySQL 到 JSON 管道是什么样的,您使用的是 DTO 还是普通的旧数组? 可以是任何东西,你应该发布你的代码 从您的描述中无法说出瓶颈在哪里。是PHP代码吗? PHP 代码能写得更高效吗?大概。但是您还没有显示代码,所以没有人可以提出改进它的建议。无论如何,准备如此庞大的结果集无论如何都需要一些时间。 您真的需要一次性获取大量数据吗?为什么不只是在需要时获取所需的数据呢?那将是最有效的。您还说您遍历数据,这是有原因的吗?当你迭代它时,你到底在做什么?您可以将整个结果转换为 json 而无需添加您自己的迭代。但正如其他人所说,我们需要更多详细信息(如您的代码等) 【参考方案1】:

可以在索引良好的表中搜索所需的行,这比下载所有行然后在应用中过滤要快得多。

【讨论】:

这很高兴知道,但应用程序的整个功能是建立在将所有数据放在一个网格中的基础上的。除了过滤之外,网格会自动对特定列进行小计和计数,类似于 Excel 的方式,因此无论过滤器如何,数据都需要可用。感谢您抽出宝贵时间发表评论。【参考方案2】:

看起来你主要是在这里转义引号。您是否尝试过在 mysql 中使用 QUOTE() 函数作为查询的一部分?

您可以查看这是否有助于作为您的选择语句的一部分。查看 this example 了解如何使用它。

那么也许您可以注释掉 foreach 循环,然后在 while 循环的结果上运行 json_encode()

我很想知道这是否适合您,以及它是否有任何性能改进。告诉我。

【讨论】:

以上是关于将 MySQL 结果转换为 JSON 的效率的主要内容,如果未能解决你的问题,请参考以下文章

将mysql结果转换为具有正确类型的json

查询Mysql表之后将结果转换为json时如何能够保持字段的原有数据类型?

使用python将mySql查询结果转换为json

提高 for 循环效率

关于pgsql 几个操作符的效率测试比较

Java将json中key值下划线转为驼峰格式