Java 实体及;实体属性。有效搜索的数据库设计

Java 实体及;实体属性。有效搜索的数据库设计,java,sql,postgresql,database-design,database-performance,Java,Sql,Postgresql,Database Design,Database Performance,过去两天,我一直在为下面描述的问题寻找合适的解决方案 在我的独立通知服务模块中,我有一个抽象消息实体。消息具有“to”、“from”、“sentAt”、“receivedAt”和其他属性。通知服务的职责是: 使用不同的注册消息提供商(SMS、电子邮件、Skype等)发送新消息 从注册的消息提供程序接收新消息 更新已发送邮件的状态 通知服务模块作为独立模块开发,可通过SOAP协议使用。许多客户端可以使用此模块发送或搜索已接收的消息 客户端希望在发送消息时附加一些属性(~smth-like标记),以

过去两天,我一直在为下面描述的问题寻找合适的解决方案

在我的独立通知服务模块中,我有一个抽象消息实体。消息具有“to”、“from”、“sentAt”、“receivedAt”和其他属性。通知服务的职责是:

  • 使用不同的注册消息提供商(SMS、电子邮件、Skype等)发送新消息

  • 从注册的消息提供程序接收新消息

  • 更新已发送邮件的状态

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

    客户端希望在发送消息时附加一些属性(~smth-like标记),以便通过这些属性进一步搜索消息。这些属性只有在客户端环境中才有意义

    例如,客户端A可能希望发送消息并保存以下自定义属性: 1.系统发送消息的用户的内部系统id 2.区分标志(id是否与用户/管理员或客户端相关) 3.通知标志(通知/警报/…)

    客户端B可能希望发送消息并保存另一组自定义属性: 1.内部系统操作员id(发送sms的人) 2.用于发送消息的模板id

    客户端可以使用自定义属性来搜索已发送的邮件

    例如:

  • 客户端A可以找到在[Date 1;Date 2]之间发送给管理员用户的具有“警报”状态的SMS消息

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

  • 当然,数据应该逐页获取

    首先,我创建了以下数据库模型:

    要查找具有指定属性的所有邮件,我尝试使用查询:

    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
    
    在具有小数据的数据库中,查询工作得很好(尽管我觉得不是很好)。我决定检查结果,看是否有真正等待的数据。 所以我生成了10000条消息,其中包含400000个自定义属性和检查结果。执行时间约为2分钟。最耗时的操作是以下子选择:

    SELECT message_id FROM custom_message_properties
                      WHERE CONCAT(CONCAT(key, ':'), value) IN ('property1:value1', 'property2:value2')
    
    我知道字符串比较非常慢,因为没有使用数据库索引功能。我决定改变数据库结构,将“key”和“value”列合并为一个列。因此,我通过数据库方案进行了更新:

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

    因此,现在我不知道如何在应用程序架构设计没有重大变化的情况下提高性能。 我唯一的想法就是为每个客户机创建一个单独的表,其中包含所需的客户机属性

    client(i)_custom_properties {
          mid bigint, // foreign key references message (id)
          p1  type1,
          p2  type2,
          ......
          pn  type(n)
    }
    
    我花了很多时间试图找到有用的信息。我还分析了“stackoverflow”数据库,因为我觉得它应该是完全相同的。但是在“stackoverflow”中有大约50000个不同的标签。我的数据库可能没有这么多

    感谢您的帮助。提前谢谢

    我使用的项目环境:

  • Postgres数据库(9.6)
  • Java 1.8
  • Spring模块(Spring引导、Spring数据jpa+hibernate、Spring ws等)

  • 除了为每个客户端创建包含客户端属性的附加表之外,我还没有找到任何合适的解决方案。 我知道,这个解决方案没有那么灵活, 但现在搜索查询时间不到1秒


    将来,我将尝试使用noSQL数据存储解决同样的问题

    非常感谢您的反馈。我分析了这篇文章。对于我的项目,很难使用非jpa的东西,比如postgres数组和jsonb数据类型。稍后我想构建projectenv。在noSQL数据存储(如elastic search或mongodb)上,测试相同的查询。欢迎来到ORM模糊化关系模型的奇妙世界,您不需要noSQL解决方案。你只需要去掉你的模糊层,它阻止你在Postgres中使用noSQL特性。