简体   繁体   English

MySql:追加到数据库中当前值的最快方法

[英]MySql: Quickest way to append to current value in DB

I have a table with 32,000 entries. 我的桌子有32,000个条目。

Each entry has a JSON blob against it: 每个条目都有一个针对它的JSON Blob:

{
    "property1": "someValue",
    "property2": "AnotherValue"
}

I now need to append another property to this blob for every entrant so that we have: 现在,我需要为每个参与者另一个属性附加到此Blob,以便我们拥有:

{
    "property1": "someValue",
    "property2": "AnotherValue",
    "property3": "YetAnotherValue"
}

Because someValue and AnotherValue will be different for different entries I cannot just replace the old records with the new one. 因为someValueAnotherValue对于不同的条目将有所不同,所以我不能仅用新记录替换旧记录。 Instead (I'm guessing) I'm supposed to parse JSON, add property3 and return it to DB for each of the 32,000 records. 相反(我猜),我应该解析JSON,添加property3并将其返回给DB,用于32,000条记录中的每条记录。

What is the best way to achieve this? 实现此目标的最佳方法是什么? I have a MySql database which I interact with through PhpMyAdmin. 我有一个MySql数据库,可以通过PhpMyAdmin与之交互。

I tried writing a PHP script which will basically select and loop through every row, parse and append to my JSON blob and put it back up for every record. 我尝试编写一个PHP脚本,该脚本将基本上选择并循环遍历每一行,解析并追加到我的JSON blob,并为每条记录备份它。 However after I run this in a browser it simply times out on me because it takes too long to execute (I suspect it's the wait time between pulling the blob and uploading it back up for every record). 但是,在我在浏览器中运行此命令后,它只是超时了,因为执行时间太长(我怀疑这是拉出blob并将其上传回每条记录之间的等待时间)。

Any help is greatly appreciated! 任何帮助是极大的赞赏!

I would question the need to save JSON into a MySQL DB directly. 我会质疑是否需要将JSON直接保存到MySQL数据库中。 Let's say your table with the JSON blob is called my_table and it has an id field. 假设您的带有JSON Blob的表称为my_table ,它具有一个id字段。 I'd create another table, say, my_json_properties . 我将创建另一个表,例如my_json_properties There, I'd create three columns: my_table_id , property_name and property_value . 在那里,我将创建三列: my_table_idproperty_nameproperty_value Then just populate that table with the JSON properties, and adding new properties is trivial. 然后只需使用JSON属性填充该表,然后添加新属性就变得很简单。 Also remember to delete the blob column and of course to update your data access objects. 还请记住删除blob列,当然要更新您的数据访问对象。

Note: use the InnoDB storage engine so you get to make the my_json_properties.my_table_id into a foreign key that references my_table.id . 注意:请使用InnoDB存储引擎,以使my_json_properties.my_table_id成为引用my_table.id的外键。 MySQL also automatically creates an index with the foreign key columns, so it's very effective to query the properties when you just know the id in the original table. MySQL还自动使用外键列创建索引,因此当您只知道原始表中的ID时,查询属性非常有效。

You could use an UPDATE statement to add this new property to your json blob, if the json is regular, ie there's no blank after the last property and the } has got a fixed position in the next line. 如果json是常规的,则可以使用UPDATE语句将此新属性添加到json blob中,即,最后一个属性之后没有空格,并且}在下一行中具有固定位置。 Building on your example and assuming \\n as end of line you could do it like that: 以您的示例为基础,并假设\\ n为行尾,您可以这样做:

UPDATE example
SET json = REPLACE(
               json, 
               '"\n}', 
               '",\n    "property3": "some value"\n}');

Demo( http://sqlfiddle.com/#!2/db972/1 ) 演示( http://sqlfiddle.com/#!2/db972/1

A more robust approach would be by the suggestions of Marcus Adams: 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}'
    );

This will work independently of trailing spaces after the last property and leading spaces before the } , but it's still relying on the \\n as end of line. 这将独立于最后一个属性之后的尾部空格和}之前的前导空格而工作,但是它仍然依赖\\n作为行尾。

Note: 注意:

Such statements are usually much faster than row by row updating with a script. 这样的语句通常比用脚本逐行更新要快得多。

It depends on use case. 这取决于用例。 If this is a one time task, it would be MUCH better to run your script from the shell and not from browser to avoid web server and browser timeouts. 如果这是一项一次性任务,那么最好从外壳程序而不是从浏览器运行脚本,以避免Web服务器和浏览器超时。

php -f my_update_script.php

If you cannot run script from the shell for whatever reason you can try to fool the browser and web server as follows: 如果由于某种原因无法从外壳运行脚本,则可以尝试如下欺骗浏览器和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

However this approach may fail if there is caching reverse proxy in front of your web server. 但是,如果Web服务器前面有缓存反向代理,则此方法可能会失败。

MariaDb has native support for JSON format (since version 10), you may consider to switch to MariaDb. MariaDb对JSON格式(从版本10开始)具有本机支持,您可以考虑切换到MariaDb。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM