2017-06-14 149 views
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数据库中的排序键)“LIKE以%开头”。那么如何解决这个问题,因为我可能有1亿条记录?不想全表扫描..

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

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

我建议象下面

EXISTS(SELECT 1 FROM transaction_tag WHERE TAG_ID = 'ZZ' 和TRANS_ID = tr.trans_id)WHERE子句中一次为每个标签(注意:假设TR是一个别名到周边查询中的交易表)

我没有跟着这个;因为我必须对标签执行AND和OR条件,例如(“SPORTS”和“ADIDAS”)----“SHOE”和(“NIKE”或“ADIDAS”)

Update_2: 我还没有其次是位域,因为不知道红移是否有这种支持,我还假设我的系统将会有最少3500个标签,并为每个标签分配一位;这会导致每个事务的437字节,尽管只能为事务提供最多5个标记。这里有什么优化?

Solution_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|%

,查询搜索鞋(ay = 51)和SIZE_12(cq = 95)是

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

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

回答

1

可以在文件加载到S3时实现自动标记。在数据库层面进行标记在这个过程中太迟了。繁琐的,并且涉及大量的硬编码

  1. 当使用AWS s3API 例如低于 AWS s3api把标记对象--bucket --key --tagging“标签集= [{密钥加载到S3标签它=阿迪达斯,值= AY}]”

捕获通过发送和作为参数

2.load标签动态标签dynamodb作为元数据存储

3.load数据使用到红移S3 COPY co命令

+0

谢谢!但我需要研究这一点,并回到你身边。我对S3复制命令的理解是:它用于从文件批量插入行。对于我来说,每一行都会有不同的标签,但复制命令对于所有的批量插入都是一次的。 –

1

您可以将标记列存储为varchar位掩码,即严格定义的1或0的位序列,以便如果购买由标记标记,则会有1,如果不是,则会有0等。对于每一行,您将有一个0和1的序列,其长度与您拥有的标签数量相同。这个顺序是可排序的,但是你仍然需要查找中间的东西,但是你会知道在哪个特定的位置上看,所以你不需要like,只需要substring。为了进一步优化,您可以将此位掩码转换为整数值(对于每个序列它将是唯一的)并根据该值进行匹配,但AFAIK Redshift不支持此功能,您将不得不自己定义规则。

UPD:好像是最好的选择这里是保持标签在一个单独的表,并创建解开标签进入order_id, tag_id表格结构的ETL过程中,order_id分布和tag_id排序。或者,您可以创建一个视图,将该视图与订单表连接起来。然后查询具有特定标签的订单和进一步的订单汇总应该是有效的。在一张平板电脑上没有用来优化这个功能的东西,至少我不知道这样不会带来很多不必要的复杂性,而不是“关系型”解决方案。

+0

谢谢! @AlexYes。我想到了这一点,但我认为我的系统将会有最少3500个标签,每笔交易的结果为437字节,尽管交易最多可以给出5个标签。这里有什么优化? –

+0

一种方法是将所有内容都编码为整数,但由于我没有尝试过,所以我不能在这里提供建议,另一种方式我会想到的是更多“关系” - 您创建了一个具有“order_id,tag_id”,分布式通过'order_id'并按'tag_id'进行排序,并创建一个视图,将该视图与订单表连接起来。然后查找特定的标签和进一步的订单汇总应该是有效的。我不认为有什么其他的方式可以在一排排上进行优化。 – AlexYes

+0

除了上述内容,您的代码似乎并不是自定义的。根据您的指定,它只是“指定”,“品牌”,“颜色”和“大小”,并且将它们作为原始值存储在单独的编码列中会好得多。 – AlexYes