2017-04-10 63 views
0

过去两天我一直在寻找适合下面描述的问题的解决方案。实体和实体属性。有效搜索的数据库设计

在我的独立通知服务模块我有一个摘要消息实体。 消息包含'to','from','sentAt','receivedAt'和其他属性。通知服务的责任是:

  1. 使用不同的注册消息提供商(SMS,EMAIL,Skype等)发送新消息。

  2. 从注册的消息提供者收到新邮件

  3. 更新状态为已发送的邮件。

通知服务模块被开发为独立的模块,其可通过SOAP协议。许多客户可以使用此模块发送或搜索已收到的消息。

客户希望附加一些属性(〜smth类似标签),同时通过这些属性发送消息以进一步搜索消息。这些属性仅在客户环境中才有意义。

例如,客户端A可能要发送消息,并保存下列自定义属性:用户 1.内部系统ID其中系统发送消息 2.区分标志(ID是否与用户/管理员或客户端) 3.通知标志(通知/警报/ ...)

客户端B可能要发送消息,并保存另一套自定义属性: 1.内部系统操作员ID(谁发送短信) 2。用于发送消息的模板ID

客户端可以使用自定义属性来搜索已发送的消息。

例如:

  1. 客户端A能找到日期1之间[在期间发送给管理员的用户的SMS消息;日期2]具有“提醒”状态。

  2. 客户端B可以找到指定模板发送的所有通知。

当然,数据应该逐页读取。

起初,我创建了以下数据库模型:

Database scheme

要查找与指定属性的所有消息我试图用查询:

SELECT * FROM (SELECT message_id FROM custom_message_properties 
        WHERE CONCAT(CONCAT(key, ':'), value) IN ('property1:value1', 'property2:value2') 
       GROUP BY message_id having(count(*)) = 2) 
       as cmp JOIN message m ON cmp.message_id = m.id ORDER BY ID LIMIT 100 OFFSET 0 

查询工作的罚款(虽然它似乎我不太好)在数据库中使用小数据。我决定检查〜实际等待的数据的结果。 因此,我生成了10 000 000条消息,其中包含40 000 000个自定义属性并检查了结果。执行时间约为2分钟。最消耗时间的操作,下面的子选择:

SELECT message_id FROM custom_message_properties 
        WHERE CONCAT(CONCAT(key, ':'), value) IN ('property1:value1', 'property2:value2') 

据我所知,字符串比较是不使用很慢的原因数据库索引功能。我决定改变数据库结构以将'key'和'value'列合并为一个。所以,我更新的数据库方案:

Updated database scheme

我再次检查的结果。现在执行时间约为20秒。它好得多,但仍不适合用于生产。

所以,现在我不知道如何改进,而不在应用架构设计显著变化的表现。 我唯一想到的就是为每个客户端创建具有所需客户端属性的单独表格。

client(i)_custom_properties { 
     mid bigint, // foreign key references message (id) 
     p1 type1, 
     p2 type2, 
     ...... 
     pn type(n) 
} 

我花了很多时间,试图找到任何有用的信息。我还分析了'stackoverflow'数据库的原因,似乎我应该是完全一样的。但在'计算器'中有〜50 000个不同的标签。不是我的数据库可能有。

任何帮助表示赞赏。提前致谢!

,我使用

项目环境:

  1. Postgres数据库(9.6)
  2. 的Java 1.8
  3. Spring模块(弹簧启动,弹簧数据的JPA +休眠,春天-WS等) 。
+0

http://www.databasesoup.com/2015/01/tag-all-things.html –

+0

非常感谢您的反馈。我分析了这篇文章。对于我的项目来说,使用非jpa的东西很困难,比如postgres数组和jsonb数据类型。 后来我想构建项目环境。在noSQL数据存储上(如弹性搜索或mongodb)并测试相同的查询。 –

+0

欢迎ORM的精彩世界 - 混淆后的关系模型 –

回答

0

我还没有发现除与客户机的每一个客户端属性创建额外的表中的任何合适的溶液。 我知道,这种解决方案是不那么灵活, 但现在搜索查询时间小于1秒。

在将来,我会尽力解决使用NoSQL数据存储同样的问题。

+0

你不需要的NoSQL解决方案。你只需要摆脱阻止你在Postgres中使用noSQL特性的混淆层。 –