【问题标题】:Memory problems when creating a large PHP array for leaflet为传单创建大型 PHP 数组时的内存问题
【发布时间】:2020-01-27 10:49:36
【问题描述】:

我有一个 MySQL 8 空间数据库,大约有 450 个条目。不幸的是,我无法在我的网络空间中使用我更熟悉的 PostGre/PostGIS。对于本地测试,我使用 Xampp 和 php 将数据加载到传单地图中。

我收到错误消息:

致命错误:第 21 行 C:\xampp\htdocs\xgis\php\test3.php 中允许的内存大小为 134217728 字节已用尽(尝试分配 135168 字节)

这指向'geometry' => json_decode($row['geo'])

全部450条记录的总数据长度约为11MB

最大的记录有 85.000 个 json 字符(主要是 SHAPE 条目)。如果我将进动从 ST_AsGeoJSON(SHAPE,5) 减少到 4,我得到 78.500 个字符。如果我将它保存到记事本大约是 80 KB

如果我使用本地:ini_set('memory_limit', '1024M'); 我得到了预期的结果。但我不想在网上使用它。所以我尝试用MYSQLI_USE_RESULT 缓冲结果,但我收到了错误消息。我已经阅读了一些关于这个问题的帖子和 php 文档,但我没有找到解决方案。

<?php
    //ini_set('memory_limit', '1024M');
    // mysqli_set_charset($conn,'utf8');
    $sql = "SELECT *, ST_AsGeoJSON(SHAPE,5) as geo FROM gem_grenzen;";

    $geojson = array(
       'type'      => 'FeatureCollection',
       'features'  => array()
    );


    $result = $conn->query($sql, MYSQLI_USE_RESULT);

        while($row = $result->fetch_assoc()) {
            $properties = $row;
            unset($properties['geo']);
            unset($properties['SHAPE']);

            $feature = array(
                 'type' => 'Feature',
                 'geometry' => json_decode($row['geo']), 
                 'properties' => $properties 
            );
            array_push($geojson['features'], $feature);

        }

    echo 'var $foo =';
    echo json_encode($geojson, JSON_NUMERIC_CHECK);
    echo "; \r\n";
    echo 'L.geoJSON($foo,{style:style_gem}).addTo(map);';
    ?>

【问题讨论】:

  • 你遇到了什么错误?
  • 为什么你忽略了错误信息中最重要的部分?指向发生错误的实际行的指针?它指向 json_encode 吗?如果有,和mysqli有什么关系?
  • > 致命错误:第 21 行 C:\xampp\htdocs\xgis\php\test3.php 中允许的内存大小为 134217728 字节已用尽(试图分配 135168 字节) 这指向 'geometry' =&gt; json_decode($row['geo'])
  • 谢谢。看来这是您拥有的数据量,而不是 mysqli 的责任。一个记录的大小是多少?你真的需要返回所有数兆字节的 json 吗?您确定需要返回 whole 似乎是利维坦“几何”数组吗?可以减少返回的数据量吗?
  • 最大记录有 85.000 个 json 字符(主要是 SHAPE 条目)。如果我将岁差从 ST_AsGeoJSON(SHAPE,5) 减少到 4,我会得到 78.500 个字符。如果我将它保存到 noteapd,它大约是 80 KB。没想到这会是个问题。但可以肯定的是,代码行 $result = $conn-&gt;query($sql, MYSQLI_USE_RESULT); 是否正确或/以及是否有另一种方法可以像 zip 一样传递 geojson。速度并不是真正的要求。

标签: php json geospatial geojson


【解决方案1】:

我已经使用 Xdebug https://xdebug.org 调试/跟踪了我的脚本,设置为 xdebug.auto_tracexdebug.show_mem_delta。结果内存问题是由array_push($geojson['features'], $feature);引起的

0.4779  130073936   -44160         -> json_decode() C:\xampp\htdocs\xgis\php\test3.php:22
0.4783  130459928  +385992         -> array_push() C:\xampp\htdocs\xgis\php\test3.php:25
0.4784  130459928       +0         -> mysqli_result->fetch_assoc() C:\xampp\htdocs\xgis\php\test3.php:14
0.4785  130542744   +82816         -> json_decode() C:\xampp\htdocs\xgis\php\test3.php:22
0.4798  131909512 +1366768         -> array_push() C:\xampp\htdocs\xgis\php\test3.php:25
0.4799  131909512       +0         -> mysqli_result->fetch_assoc() C:\xampp\htdocs\xgis\php\test3.php:14
0.4799  131853048   -56464         -> json_decode() C:\xampp\htdocs\xgis\php\test3.php:22
0.4806  132541400  +688352         -> array_push() C:\xampp\htdocs\xgis\php\test3.php:25
0.4806  132541400       +0         -> mysqli_result->fetch_assoc() C:\xampp\htdocs\xgis\php\test3.php:14

所以我必须用leaflet featuregroup 重写代码并将每条记录添加为自己的变量而不是一个大数组。

【讨论】:

  • 您是否尝试使用 $geojson['features'][] = $feature 而不是数组推送?
  • $geojson['features'][] = $feature 并没有真正改变什么。我可以再加载大约 10 条记录。 0.5694 144214376 +896 -&gt; json_decode() C:\xampp\htdocs\xgis\php\test3.php:23 0.5701 144726760 +512384 -&gt; mysqli_result-&gt;fetch_assoc() C:\xampp\htdocs\xgis\php\test3.php:15 0.5701 144719448 -7312 -&gt; json_decode() C:\xampp\htdocs\xgis\php\test3.php:23 0.5706 145130256 +410808 -&gt; mysqli_result-&gt;fetch_assoc() C:\xampp\htdocs\xgis\php\test3.php:15
猜你喜欢
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-27
  • 2014-08-16
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
相关资源
最近更新 更多