2

我想在每笔交易中存储用户购买的自定义标签,例如,如果用户购买了鞋子,那么标签是"SPORTS", "NIKE", SHOES, COLOUR_BLACK, SIZE_12,..

这些标签是卖家有兴趣查询回以了解销售情况。

我的想法是,当新标签出现时,为该标签创建新代码(类似于哈希码,但顺序),代码从"a-z"26 个字母开始,然后"aa, ab, ac...zz"继续。现在,将一笔交易中给定的所有标签保存在tag (varchar)用 分隔的一列中"|"

让我们假设映射是(在应用程序级别)

"SPORTS" = a
"TENNIS" = b
"CRICKET" = c
...
...
"NIKE"  = z        //Brands company
"ADIDAS" = aa
"WOODLAND" = ab
...
...
SHOES   = ay
...
...
COLOUR_BLACK = bc
COLOUR_RED = bd
COLOUR_BLUE = be
...
SIZE_12 = cq
...

所以存储上面的购买交易,标签会像tag="|a|z|ay|bc|cq|"现在允许卖家通过添加WHERE条件搜索所售鞋子的数量tag LIKE %|ay|%。现在的问题是我不能将索引(redshift db 中的排序键)用于“LIKE 以 % 开头”。那么如何解决这个问题,因为我可能有 1 亿条记录?不想全表扫描..

任何解决方案来解决这个问题?

Update_1:我没有遵循bridge table概念(交叉引用表),因为我想在搜索指定标签后对结果执行分组。当两个标签在单个事务中匹配时,我的解决方案将只给出一行,但桥表会给我两行?那么我的 sum() 将加倍。

我得到如下建议

EXISTS (SELECT 1 FROM transaction_tag WHERE tag_id = 'zz' and trans_id = tr.trans_id) 在 WHERE 子句中为每个标签一次(注意:假设 tr 是周围查询中事务表的别名)

我没有遵循这个;因为我必须对标签执行 AND 和 OR 条件,例如 ("SPORTS" AND "ADIDAS") ---- "SHOE" AND ("NIKE" OR "ADIDAS")

Update_2:我没有关注位域,因为不知道 redshift 有这种支持,所以我假设我的系统是否将有至少 3500 个标签,并为每个标签分配一个位;这导致每笔交易有 437 个字节,尽管最多只能为一笔交易提供 5 个标签。这里有什么优化吗?

解决方案_1:

我曾考虑将最小值(SMALL_INT)和最大值(SMALL_INT)与标签列一起添加,并对其应用索引。

所以像这样

"SPORTS" = a = 1
"TENNIS" = b = 2
"CRICKET" = c = 3
...
...
"NIKE"  = z  = 26
"ADIDAS" = aa = 27

所以我的列值是

`tag="|a|z|ay|bc|cq|"` //sorted?
`minTag=1`
`maxTag=95` //for cq

并且搜索鞋子的查询(ay = 51)是

maxTag <= 51 AND tag LIKE %|ay|%

搜索 shoe(ay=51) AND SIZE_12 (cq=95) 的查询是

minTag >= 51 AND maxTag <= 95 AND tag LIKE %|ay|%|cq|%

这会带来什么好处吗?请提出任何替代方案。

4

2 回答 2

1

您可以在文件加载到 S3 时实现自动标记。在数据库级别进行标记在此过程中为时已晚。乏味且涉及大量硬编码

  1. While loading to S3 tag it using the AWS s3API example below aws s3api put-object-tagging --bucket --key --tagging "TagSet=[{Key=Addidas,Value=AY}]"

capture tags dynamically by sending and as a parameter

2.load the tags to dynamodb as a metadata store

3.load data to Redshift using S3 COPY command

于 2017-06-15T08:33:53.807 回答
1

您可以将 tags 列存储为 varchar 位掩码,即严格定义的 1 或 0 的位序列,这样如果购买被标签标记,则为 1,否则为 0,以此类推。对于每一行,您将有一个 0 和 1 的序列,其长度与您拥有的标签数量相同。这个序列是可排序的,但是您仍然需要查找中间,但是您会知道要查找的特定位置,因此您不需要like, 只是substring. 为了进一步优化,您可以将此位掩码转换为整数值(它将对每个序列都是唯一的)并基于此进行匹配,但 AFAIK Redshift 尚不支持开箱即用,您必须自己定义规则。

UPD:看起来最好的选择是将标签保存在一个单独的表中,并创建一个 ETL 流程,将标签解包为 的表格结构order_id, tag_id,由 分发order_id并按 排序tag_id。或者,您可以创建一个视图,将这个视图与订单表连接起来。然后查找具有特定标签的订单和订单的进一步聚合应该是有效的。在平面表中优化这一点没有灵丹妙药,至少我不知道与“关系”解决方案相比不会带来很多不必要的复杂性。

于 2017-06-16T00:37:13.100 回答