我有一张包含32,000个条目的表格。
每个条目都有一个JSON blob:
{
"property1": "someValue",
"property2": "AnotherValue"
}
我现在需要为每个参赛者追加另一个属性到这个blob,以便我们拥有:
{
"property1": "someValue",
"property2": "AnotherValue",
"property3": "YetAnotherValue"
}
由于someValue
和AnotherValue
对于不同的条目会有所不同,因此我不能仅使用新记录替换旧记录。相反(我猜)我应该解析JSON,添加property3
并将其返回到DB,以获取32,000条记录中的每一条。
实现这一目标的最佳方法是什么?我有一个MySql数据库,我通过PhpMyAdmin进行交互。
我尝试编写一个PHP脚本,它基本上会选择并遍历每一行,解析并附加到我的JSON blob并为每条记录重新启动它。然而,当我在浏览器中运行它之后,它只会超时我,因为它需要很长时间才能执行(我怀疑它是拉动blob并将其上传回每条记录之间的等待时间)。
非常感谢任何帮助!
答案 0 :(得分:1)
我会质疑是否需要直接将JSON保存到MySQL数据库中。我们假设您的带有JSON blob的表名为my_table
,并且它有一个id
字段。我要创建另一个表格,例如my_json_properties
。在那里,我创建了三列:my_table_id
,property_name
和property_value
。然后只使用JSON属性填充该表,添加新属性是微不足道的。还记得删除blob列,当然还要更新数据访问对象。
注意:使用InnoDB存储引擎,以便将my_json_properties.my_table_id
转换为引用my_table.id
的外键。 MySQL还会自动使用外键列创建索引,因此当您只知道原始表中的id时,查询属性非常有效。
答案 1 :(得分:1)
如果json是常规的,你可以使用UPDATE语句将这个新属性添加到你的json blob,即在最后一个属性之后没有空白,并且}在下一行中有一个固定的位置。在你的例子的基础上,并假设\ n作为行尾你可以这样做:
UPDATE example
SET json = REPLACE(
json,
'"\n}',
'",\n "property3": "some value"\n}');
演示(http://sqlfiddle.com/#!2/db972/1)
Marcus Adams建议采用更有力的方法:
UPDATE example
SET json =
CONCAT(
TRIM(
TRAILING FROM TRIM(
TRAILING '\n' FROM TRIM(
TRAILING FROM SUBSTRING_INDEX(json, '}', 1)
)
)
),
',\n "property3": "some value"\n}'
);
这将独立于}
之前的最后一个属性和前导空格之后的尾随空格,但它仍然依赖于\n
作为行尾。
注意:强>
这些语句通常比使用脚本逐行更新快得多。
答案 2 :(得分:0)
这取决于用例。 如果这是一次性任务,那么从shell而不是从浏览器运行脚本会更好,以避免Web服务器和浏览器超时。
php -f my_update_script.php
如果由于某种原因无法从shell运行脚本,您可以尝试欺骗浏览器和Web服务器,如下所示:
set_time_limit(3600*2); // two hours should be enougth?
// turn off output buffering
while (ob_end_flush());
ob_implicit_flush();
// Your mysql fetch..update loop here
// begin loop
echo 'Something useful every iteration to let them know your script is alive :)';
// end loop
但是,如果在Web服务器前面存在缓存反向代理,则此方法可能会失败。
MariaDb本身支持JSON格式(从版本10开始),您可以考虑切换到MariaDb。