Performance 如何设计在分析数据库上查询多个标签

Performance 如何设计在分析数据库上查询多个标签,performance,amazon-redshift,database-tuning,Performance,Amazon Redshift,Database Tuning,我想在每笔交易中存储用户购买的自定义标签,例如,如果用户购买了鞋子,则标签为SPORTS、NIKE、shoes、Color_BLACK、SIZE_12、 卖方有兴趣查询这些标签以了解销售情况 我的想法是,当有新的标记出现时,创建新的代码,比如hashcode,但对该标记是顺序的,代码从a-z 26个字母开始,然后是aa,ab,ac…zz。现在,用|分隔,将一个事务中给定的所有标记保留在名为tag varchar的一列中 让我们假设映射在应用程序级别 "SPORTS" = a "TENNIS" =

我想在每笔交易中存储用户购买的自定义标签,例如,如果用户购买了鞋子,则标签为SPORTS、NIKE、shoes、Color_BLACK、SIZE_12、

卖方有兴趣查询这些标签以了解销售情况

我的想法是,当有新的标记出现时,创建新的代码,比如hashcode,但对该标记是顺序的,代码从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
...
因此,存储上述购买交易时,标签将类似于标签=| a | z | ay | bc | cq |,现在允许卖家通过添加WHERE条件标签(如%| ay |%)来搜索售出的鞋子数量。现在的问题是,对于以%开头的LIKE,我不能在redshift db中使用索引排序键。既然我可能有1亿条记录,那么如何解决这个问题呢?不需要全表扫描

有解决办法吗

更新1: 我没有遵循桥接表概念交叉引用表,因为我想在搜索指定标记后对结果执行分组。当两个标记在单个事务中匹配时,我的解决方案将只给出一行,但桥接表将给出两行?那么我的总数将加倍

我得到如下建议

存在从事务标记中选择1,其中标记id='zz'和事务id =tr.trans_id在WHERE子句中为每个标记注释一次:假设tr是周围查询中事务表的别名

我没有这样做;因为我必须在标签上执行和/或条件,例如运动和阿迪达斯-鞋和耐克或阿迪达斯

更新2: 我没有遵循位域,因为不知道红移有这种支持,我假设我的系统将有至少3500个标签,并为每个标签分配一位;这导致每个事务有437个字节,尽管一个事务最多只能提供5个标记。这里有优化吗

解决方案1:

我曾经考虑过在tags列中添加min SMALL_INT和max value 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
搜索shoeay=51的查询是


maxTag=51和maxTag您可以在文件加载到S3时实现自动标记。在DB级别进行标记在该过程中为时已晚。冗长且涉及大量硬编码

加载到S3时,使用AWS s3API对其进行标记 下面的例子 aws s3api放置对象标记-bucket-key-tagging标记集=[{key=Addidas,Value=AY}] 通过发送和作为参数动态捕获标记

2.将标记作为元数据存储加载到dynamodb


3.使用S3 COPY命令将数据加载到红移中

您可以将tags列存储为varchar位掩码,即严格定义的位序列为1或0,这样,如果购买由tag标记,则每行将有1,否则将有0,以此类推,您将拥有一个0和1的序列,其长度与您拥有的标记数相同。这个序列是可排序的,但是您仍然需要在中间查找,但是您将知道在哪个特定位置查找,所以您不需要像子字符串一样。为了进一步优化,您可以将此位掩码转换为整数值,它对于每个序列都是唯一的,并基于此进行匹配,但AFAIK Redshift不支持这一点,您必须自己定义规则


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

谢谢!但我需要研究一下,然后再打给你。我对S3复制命令的理解是;它用于批量插入文件中的行。对我来说,每一行都有不同的标签,但复制命令是一次用于所有批插入…谢谢@亚历克西斯。我想到了这一点,但我假设我的系统将至少有3500个标记,这将导致每个事务437字节,尽管一个事务最多可以有5个标记。这里有什么优化方法吗?一种方法是将所有内容编码为整数,但由于我没有尝试过,所以我不能在这里给出太多建议,另一种方法我认为更为相关-创建一个具有order\u id、tag\u id、按order\u id分布并按tag\u id排序的表,并创建一个将this与order表连接起来的视图。然后查找特定标记和订单的进一步聚合
它应该是高效的。我不认为有任何其他方法可以在一行中优化它。除了上面提到的,你的标签似乎不是定制的。根据您指定的内容,它只是名称、品牌、颜色和大小,最好将它们作为原始值存储在单独的编码列中。