我正在尝试使用mysql json特性识别时间序列上的趋势标记(基于最大点击量)。下面是我的table
CREATE TABLE TAG_COUNTER (
account varchar(36) NOT NULL,
time_id INT NOT NULL,
counters JSON,
PRIMARY KEY (account, time_id)
)
在每个webapi请求中,我将获得每个帐户的多个不同标记,并根据标记的数量,准备 INSERT ON DUPLICATE KEY UPDATE
查询。下面的示例显示了带有两个标记的插入。
INSERT INTO `TAG_COUNTER`
(`account`, `time_id`, `counters`)
VALUES
('google', '2018061023', '{"tag1": 1, "tag2": 1}')
ON DUPLICATE KEY UPDATE `counters` =
JSON_SET(`counters`,
'$."tag1"',
IFNULL(JSON_EXTRACT(`counters`,
'$."tag1"'), 0) + 1,
'$."tag2"',
IFNULL(JSON_EXTRACT(`counters`,
'$."tag2"'), 0) + 1
);
time\u id是yyyymmddhh,它是每行的每小时聚合。
现在我的问题是检索树标签。下面的查询将为我提供tag1的聚合,但在进行此查询之前,我们将不知道这些标记。
SELECT
SUBSTRING(time_id, 1, 6) AS month,
SUM(counters->>'$.tag1')
FROM TAG_COUNTER
WHERE counters->>'$.tag1' > 0
GROUP BY month;
所以我需要通用的groupbyquery和orderby来获取时间hourly/daily/monthly的趋势标签。
预期的输出示例为
Time(hour/day/month) Tag_name Tag_count_value(total hits)
当我在网上搜索的时候,每一个地方都像下面提到的那样 {"tag_name": "tag1", "tag_count": 1}
而不是直接 {"tag1" : 1}
他们在小组里用的是tag\u的名字。
q1)那么,是否总是强制使用公共已知的json密钥来执行分组依据。。?
q2)如果我必须这样做,那么对于这个新的json标签/值结构,我的insert on duplicate key update查询有什么变化?因为计数器必须在不存在时创建,并且在存在时应递增1。
q3)我必须维护对象数组吗
[
{"tag_name": "tag1", "tag_count": 2},
{"tag_name": "tag2", "tag_count": 3}
]
或者像下面这样的物体?
{
{"tag_name": "tag1", "tag_count": 2},
{"tag_name": "tag2", "tag_count": 3}
}
那么,在趋势计数的插入和检索方面,哪一个优于json结构呢?
问题4)我可以用现有的吗 {"key" : "value"}
格式化而不是 {"key_label" : key, "value_lable" : "value"}
有可能提取出趋势。。?既然我这么想 {"key" : "value"}
非常直率,善于表现。
问题5)在检索我正在使用的 SUBSTRING(time_id, 1, 6) AS month
. 它能使用索引吗?
或者我需要创建多个列,比如 time_hour(2018061023)
, time_day(20180610)
, time_month(201806)
并对特定列使用查询?
或者我可以使用mysql日期时间函数吗?它会使用索引来更快地检索吗?
请帮忙。
2条答案
按热度按时间qyzbxkaa1#
正如我在评论中所说的,我认为离开json是一条出路。但是,如果您想继续使用json,这个函数(我对这个问题的回答中的函数的直接副本,请参阅它在那里做什么的解释)和过程将执行您想要的操作。
这个过程与我的另一个答案中的过程类似,因为它找到了与给定的子字符串相关联的所有不同的标记
time_id
(指定为参数)并对与每个标记关联的值求和。然后,将单个标记和计数写入临时表,然后从临时表中按时间段和标记名称分组进行选择。一些例子是基于你之前问题的有限样本数据。在这些例子中
@timeval
相当于time_id
列。输入数据:呼叫
count_tags('@timeval')
:呼叫
count_tags('SUBSTRING(@timeval, 1, 6)')
:请注意,您还可以使用
json_sum_merge
简化你的工作INSERT
查询,例如。结果:
关于你回答的具体问题:
不。这个答案表明它可以用你现有的数据格式来完成。
不适用。
不适用。
是的,你可以坚持现有的
{"key" : "value"}
格式因为我们要检查每一个入口
tag_counter
为了得到标签列表,索引对该部分是不利的。对于临时表,我在Time
以及Tag_Name
列应该有利于速度,因为它们直接用于GROUP BY
条款。如果您要维护一个键列表(例如,在一个单独的表中,由插入/更新/删除到
tag_counter
)这个代码可以变得更加简单和高效。但这是另一个问题。dgsult0t2#
我看不出有什么好的理由,为什么在这里使用json。同样不清楚的是,为什么您认为mysql中的“nosql模式”会做得更好。
你可能需要这样的东西:
这将简化您的查询。insert语句如下所示:
select语句可能是这样的
请注意,我没有尝试为数据大小和性能优化表/模式。那将是另一个问题。但您必须看到,现在的查询要简单得多。