Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何高效地刷新昂贵查询的结果?_Sql_Database_Performance - Fatal编程技术网

Sql 如何高效地刷新昂贵查询的结果?

Sql 如何高效地刷新昂贵查询的结果?,sql,database,performance,Sql,Database,Performance,我有一个应用程序,它执行一个昂贵的查询来填充UI。UI需要定期刷新并显示符合原始查询条件的新数据。我希望第二个查询尽可能高效,只返回符合条件的新数据。我该怎么做 例如,我的第一个查询如下: 从一些非常大的表格中选择* 最明显的想法是在原始查询中添加一个新的限定条件。假设我有一个名为update_timestamp的列,它存储创建行或上次更新行的时间戳。为了简化这个问题,我们假设只有一个数据库服务器,并且这个时间戳是在执行insert/update语句时从数据库服务器操作系统时间填充的。还假

我有一个应用程序,它执行一个昂贵的查询来填充UI。UI需要定期刷新并显示符合原始查询条件的新数据。我希望第二个查询尽可能高效,只返回符合条件的新数据。我该怎么做

例如,我的第一个查询如下:

从一些非常大的表格中选择*

最明显的想法是在原始查询中添加一个新的限定条件。假设我有一个名为update_timestamp的列,它存储创建行或上次更新行的时间戳。为了简化这个问题,我们假设只有一个数据库服务器,并且这个时间戳是在执行insert/update语句时从数据库服务器操作系统时间填充的。还假设时钟具有足够的分辨率,使得没有两个时间戳是相同的。添加另一个假设,即时钟值永远不会减少。我知道这些都是不切实际的假设

借助这个新列(以及该列上的索引),我使用以下查询执行刷新(其中X是原始查询中任何结果返回的最高更新时间戳):

从更新时间戳>X的某个大表格中选择*

我还有一个问题。由于update_时间戳是在语句执行时分配的,因此两个同时写入记录的事务可能会以一个顺序执行insert/update语句,但以相反的顺序提交。因此,具有较大更新时间戳的行将在具有较小更新时间戳的行之前存在。如果应用程序的刷新查询在这两次提交之间执行,它将永远看不到第二次提交的数据!它将在当前刷新中丢失,下一次刷新也不会拾取它。我不能接受这种可能性。

序列化写入 为了解决这个问题,我似乎需要在选择update\u时间戳之前,通过在某个锁上同步来序列化对某个真正大的\u表的写入。然后,在提交插入/更新后立即释放锁。通过这种方法,我可以保证记录不会因update\u时间戳而被写错顺序

如果数据库写入不频繁或已经是单线程的,我可能不关心这一点,但让我们假设对某些真正的大表的写入是频繁且并行的

有没有解决方案不需要我序列化写操作?

替代溶液 我想我可以改为使用以下查询(其中Y是我认为update\u timestamp值可能不符合顺序的距离的一些模糊因素):

从更新时间戳>(X-Y)的某个大表格中选择*

我可以这样做,但我不愿意冒着出错的风险,我的应用程序因此而悄悄地丢失了数据。也许我会将Y设置得相当大,以尽量避免出现这种情况,但我的应用程序的性能会因此受到影响,而且我仍然可能会出错。例如,有人可能会更改数据库服务器上的时钟,而我的错误因素现在已经远远超过了

我可以使用逻辑时钟而不是操作系统时钟,但在选择下一个时钟值之前,我仍然必须序列化,或者我又回到了同样的问题,即选择逻辑时钟值的机会和提交数据库的顺序不一致。我也可以在逻辑时钟上使用模糊因素,但仍有出错的空间。

分区序列化写入 我还考虑过对数据进行分区,这样就不必将所有写操作同步到某个非常大的表中。比如说,我有一个列some_attribute,这是一种划分某个真正的大表的自然方式,因此对某个属性的给定值的并发写入相对较少。在这种情况下,我只保证分区内update_时间戳的插入/更新顺序。然后,我的刷新查询变为以下内容:

X1、X2、X3…是我上次查询时看到的最高更新时间戳值。A1、A2、A3…是我的查询关心的某个_属性的值。事实上,我最初的查询中也会有一些_属性限定,但我从讨论中排除了它,以便在开始时让事情更简单。因此,第一个问题应该是:

从某个大表格中选择*,其中某个属性位于(A1、A2、A3,…)

似乎这种分区序列化技术是我能想到的最好的方法。我知道其他人以前肯定也解决过同样的问题。似乎在为某些类型的数据实现缓存时可能会出现这种情况。我在谷歌上搜索过,但我似乎很难选择能够引导我讨论这个问题的搜索词。   有没有人有类似问题的经验可以分享

在我对这个主题做一些研究时,我偶然发现了Oracle的闪回查询功能[1]。对于这个使用基于SCN的查询的用例来说,这似乎是有意义的,但我不一定能指望访问这个特性,因为我的系统不一定在Oracle上运行


[1]

想知道为什么no1到目前为止一直在回复,但无论如何,这可能是你的一个选择: 不要更新所有记录,而是创建一个名为“update_groups”的辅助表,然后将记录链接到该组,并在该组上设置时间戳,而不是单独的记录。你也可以用一个布尔值来代替时间戳“IsUpdated”…或其他什么。 但这只有在记录可以分组的情况下才有效,如果您只有一个大的记录列表,那么您可以创建一个或多个记录的表
select * from some_really_big_table where
(some_attribute = A1 and update_timestamp > X1)
or (some_attribute = A2 and update_timestamp > X2)
or (some_attribute = A3 and update_timestamp > X3)
...