使用实体化视图更快地从大型表中检索数据
Retrieve data faster from large tables using Materialized Views
我们有一个table来存储用户登录的日志,user_login_log。 table 每次用户登录时都会收到一条记录。
我们有一个用例来获取每个用户的上次登录时间戳,并且会经常获取此数据。要求是这个数据要快速加载。
要求
- 应快速加载数据。
- 数据不应过时。
日志table可以有几万条记录,每次查询都会很慢。我们提出了两种快速检索数据的方法。
方法 1:我们最初的想法是使用实体化视图。
这种方法的问题在于,随着user_login_logtable中数据的增加,刷新物化视图的查询会变慢,因此使插入、更新和删除操作变慢。
方法 2:另一个想法是使用专用快照 table 来存储最新的登录数据。
然后直接从快照中检索数据table。这种方法的问题是我们将在两个 table 中维护相同的数据,并且触发器函数将负责维护数据完整性。
这些方法中哪种更适合我们的用例?有没有其他方法可以更有效地过滤和检索所需的数据?
您的第一种方法没有多大意义。为什么构建一个具有您需要的确切信息的触发器,只是为了丢弃该信息并让它从头开始重建整个 table?是的,当然会很慢。
在您的第二种方法中,为什么创建第二个 table 只是为了保存一列信息?难道您没有可以添加列的 "app_user" table 吗?
The issues with this approach is that we'll be maintaining the same data in two tables and the trigger function will be responsible for maintaining data integrity.
我认为这没有问题。这不是触发器的用途吗?只需正确编码,并确保用户登录事件在其自己的事务中,以避免在不适当的时间内锁定记录。
另一种选择是编写一个递归 CTE 来对您现有的 user_login_log table 执行 loose index scan。这可能足够快以避免在写入时必须做任何特殊的事情。
您似乎有 2 个问题。简单的一个,如何存储数据。这是正在讨论的问题。正如建议的那样,最简单的只是您的用户 table 中的一列,但提出了您是否需要登录历史记录的问题。如果是这样,那么还要创建一个 login_hist table 并在 user_table 上使用触发器填充它。其他需要考虑的是其他应用程序(现在或将来)是否共享同一个数据库。
更困难的问题可能是:您首先如何捕获数据?你建议了一个触发器,但触发器是什么。不幸的是,Postgres 不提供登录触发器。也许使用 login_hook 扩展名。但这似乎是一个非标准的扩展,很多安装都不允许安装它。
祝你好运!
我们有一个table来存储用户登录的日志,user_login_log。 table 每次用户登录时都会收到一条记录。
我们有一个用例来获取每个用户的上次登录时间戳,并且会经常获取此数据。要求是这个数据要快速加载。
要求
- 应快速加载数据。
- 数据不应过时。
日志table可以有几万条记录,每次查询都会很慢。我们提出了两种快速检索数据的方法。
方法 1:我们最初的想法是使用实体化视图。
这种方法的问题在于,随着user_login_logtable中数据的增加,刷新物化视图的查询会变慢,因此使插入、更新和删除操作变慢。
方法 2:另一个想法是使用专用快照 table 来存储最新的登录数据。
然后直接从快照中检索数据table。这种方法的问题是我们将在两个 table 中维护相同的数据,并且触发器函数将负责维护数据完整性。
这些方法中哪种更适合我们的用例?有没有其他方法可以更有效地过滤和检索所需的数据?
您的第一种方法没有多大意义。为什么构建一个具有您需要的确切信息的触发器,只是为了丢弃该信息并让它从头开始重建整个 table?是的,当然会很慢。
在您的第二种方法中,为什么创建第二个 table 只是为了保存一列信息?难道您没有可以添加列的 "app_user" table 吗?
The issues with this approach is that we'll be maintaining the same data in two tables and the trigger function will be responsible for maintaining data integrity.
我认为这没有问题。这不是触发器的用途吗?只需正确编码,并确保用户登录事件在其自己的事务中,以避免在不适当的时间内锁定记录。
另一种选择是编写一个递归 CTE 来对您现有的 user_login_log table 执行 loose index scan。这可能足够快以避免在写入时必须做任何特殊的事情。
您似乎有 2 个问题。简单的一个,如何存储数据。这是正在讨论的问题。正如建议的那样,最简单的只是您的用户 table 中的一列,但提出了您是否需要登录历史记录的问题。如果是这样,那么还要创建一个 login_hist table 并在 user_table 上使用触发器填充它。其他需要考虑的是其他应用程序(现在或将来)是否共享同一个数据库。
更困难的问题可能是:您首先如何捕获数据?你建议了一个触发器,但触发器是什么。不幸的是,Postgres 不提供登录触发器。也许使用 login_hook 扩展名。但这似乎是一个非标准的扩展,很多安装都不允许安装它。
祝你好运!