在存储过程中解析 JSON 没有优雅的方法。您可能会想出某种组合来使用字符串函数提取您需要的项目。但这听起来令人讨厌且不可靠。
为元数据创建表
根据我的经验,处理这种扩展操作的一个好方法是添加一个新表,而不是尝试向现有表添加列。
您的新表,我们称之为metadata,将包含以下列:
id PK, also FK to tweet table. NOT autoincrement.
created_at copied over from tweet table.
user_id the value of the user_id you extract.
lat FLOAT value for coordinate, NULL if no coordinate was available
lon FLOAT value or NULL like LAT.
您可以像分区推文表一样对metadata 表进行分区。这就是我在此设计中复制created_at 字段的原因。
填充元数据表
然后您可以运行将填充此表的后台客户端程序(使用 python 或任何适合您的语言)。它将从 tweets 表中读取行,然后在此处插入相应的行。您可能可以分批执行 100 行左右,并使其相当快。
如果我是你,我会使用这样的查询来检索每批要更新的推文。
SELECT tweet.id, tweet.created_at, tweet.json
FROM tweet
LEFT JOIN metadata ON tweet.id = metadata.id
WHERE metadata.id IS NULL
LIMIT 100
这将获取在 metadata 中没有对应行的 100 行(确切地说是哪些行>这在形式上是不可预测的,但没关系)。
然后,提取元数据并插入您需要的行。请注意,在许多情况下,INSERT 比 UPDATE 快得多。此外,您可以使用具有此模式的查询执行多行 INSERT:
INSERT INTO metadata (id, created_id, user_id, lat, long) VALUES
(?,?,?,?,?),
(?,?,?,?,?),
(?,?,?,?,?),
(?,?,?,?,?),
(?,?,?,?,?)
这种多行 INSERT 通过减少服务器往返次数使事情变得更快。
您可以简单地循环这些 100 行批次,直到查询不再获得任何行。这个程序可能会运行很多小时来处理你的 megarow,但这没关系。使用此批处理策略,您可以随时重新启动它,它将从上次中断的地方开始。
如果需要,您甚至可以让它运行以在新推文到达时填充新的元数据。
请注意,它没有设置为运行多个更新程序实例。如果你愿意,你需要对交易做一些事情。 IMO 这不值得麻烦。
使用元数据
当您需要使用元数据时,您可以使用如下查询:
SELECT tweet.whatever, tweet.whatever,
metadata.user_id, metadata.lat, metadata.lon
FROM tweet
LEFT JOIN metadata ON tweet.id = metadata.id
WHERE tweet.created_at > NOW() - INTERVAL 1 HOUR
请注意,我使用的是 LEFT JOIN 而不是 JOIN,因此即使尚未完成填充元数据的工作,您仍然可以从 tweet 获取行。
您还可以更改插入新推文的软件,以便正确插入元数据。