我正在为一个简单的银行数据库编写架构。以下是基本规格:
银行应用程序将专门通过存储过程与其数据库通信。
我希望这个数据库每天接受数十万个新事务,以及更高数量级的平衡查询。为了非常快速地提供余额,我需要预先汇总它们。同时,我需要保证余额永远不会与其交易历史相矛盾。
我的选择是:
有一个单独的balances
表并执行以下操作之一:
将事务应用于transactions
和balances
表。TRANSACTION
在我的存储过程层使用逻辑来确保余额和交易始终同步。(由杰克支持。)
将交易应用到transactions
表并有一个触发器,balances
用交易金额为我更新表。
将交易应用到balances
表中,并有一个触发器transactions
为我在表中添加一个新条目,其中包含交易金额。
我必须依靠基于安全的方法来确保在存储过程之外不能进行任何更改。否则,例如,某些进程可以直接将事务插入transactions
表中,并且在该方案1.3
下相关余额将不同步。
有一个balances
索引视图,可以适当地聚合事务。存储引擎保证余额与其交易保持同步,因此我不需要依赖基于安全的方法来保证这一点。另一方面,我不能再强制余额为非负数,因为视图——甚至索引视图——不能有CHECK
约束。(由丹尼支持。)
只有一个transactions
表,但有一个额外的列来存储该交易执行后立即生效的余额。因此,用户和货币的最新交易记录也包含其当前余额。(下面由Andrew建议;由garik提出的变体。)
当我第一次解决这个问题时,我阅读了这 两个讨论并决定了 option 2
。作为参考,您可以在此处查看它的基本实现。
您是否设计或管理过这样的具有高负载配置文件的数据库?你对这个问题的解决方案是什么?
你认为我做出了正确的设计选择吗?有什么我应该记住的吗?
例如,我知道对transactions
表的架构更改需要我重建balances
视图。即使我正在归档事务以保持数据库较小(例如,将它们移到其他地方并用摘要事务替换它们),每次架构更新时都必须重建数千万个事务的视图,这可能意味着每次部署的停机时间会显着增加。
如果索引视图是要走的路,我如何保证没有余额为负?
归档交易:
让我详细说明一下存档交易和我上面提到的“摘要交易”。首先,在像这样的高负载系统中,定期存档将是必要的。我想保持余额与其交易历史之间的一致性,同时允许将旧交易转移到其他地方。为此,我将用每个用户和货币的金额摘要替换每批存档交易。
因此,例如,此交易列表:
user_id currency_id amount is_summary
------------------------------------------------
3 1 10.60 …
Run Code Online (Sandbox Code Playgroud) sql-server-2008 database-design sql-server aggregate materialized-view
是否可以在 PostgreSQL 中增量刷新物化视图,即仅针对新的或已更改的数据?
考虑这个表和物化视图:
CREATE TABLE graph (
xaxis integer NOT NULL,
value integer NOT NULL,
);
CREATE MATERIALIZED VIEW graph_avg AS
SELECT xaxis, AVG(value)
FROM graph
GROUP BY xaxis
Run Code Online (Sandbox Code Playgroud)
定期添加新值graph
或更新现有值。我想graph_avg
每隔几个小时刷新一次视图,仅针对已更新的值。但是在 PostgreSQL 9.3 中,整个表都被刷新了。这是相当耗时的。下一个版本 9.4 允许CONCURRENT
更新但它仍然刷新整个视图。有数以百万计的行,这需要几分钟。
跟踪更新和新值并仅部分刷新视图的好方法是什么?
SQL Server 2017 有几个新的存储过程:
以及 sys.messages 中的新条目:
我有一个物化视图Postgres 9.3
,我想用新列进行更新。但是,其他物化视图也依赖于该视图,并且错误消息表明当其他对象依赖于该视图时,无法删除该视图。
错误:无法删除物化视图 latest_charges 因为其他对象依赖它
从文档中还可以看出 REPLACE 关键字对物化视图无效。除了删除所有依赖对象并重建每个对象之外,还有其他捷径吗?
我们有一个具有相当大记录数(10-2000 万行)的数据仓库,并且经常运行查询来计算特定日期之间的记录数,或者计算具有特定标志的记录数,例如
SELECT
f.IsFoo,
COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo
Run Code Online (Sandbox Code Playgroud)
性能并不差,但可能相对缓慢(在冷缓存上可能 10 秒)。
最近我发现我可以GROUP BY
在索引视图中使用,因此尝试了类似于以下内容
CREATE VIEW TestView
WITH SCHEMABINDING
AS
SELECT
Date,
FlagId,
COUNT_BIG(*) AS WidgetCount
FROM Widgets
GROUP BY Date, FlagId;
GO
CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
Date,
FlagId
);
Run Code Online (Sandbox Code Playgroud)
因此,我的第一个查询的性能现在 < 100 毫秒,结果视图和索引 < 100k(尽管我们的行数很大,但日期和标志 ID 的范围意味着此视图仅包含 1000-2000 行)。
我认为这可能会降低对 Widget 表的写入性能,但没有 - 据我所知,向该表中插入和更新的性能几乎不受影响(另外,作为数据仓库,该表很少更新反正)
对我来说,这似乎好得令人难以置信——是吗?以这种方式使用索引视图时需要注意什么?
performance index sql-server materialized-view query-performance
我正在使用 MySQL 5.6。我无法像在 Oracle 中那样创建物化视图。我见过一两个像 Flexview 这样的解决方案。
谁能告诉我在 MySQL 中创建物化视图的最佳方法(如 Oracle 中的自动刷新),并且复杂性最低?
我想知道如何在 Postgres 中查询物化视图的定义。作为参考,我希望做的与您可以为常规视图做的非常相似:
SELECT * FROM information_schema.views WHERE table_name = 'some_view';
Run Code Online (Sandbox Code Playgroud)
它为您提供以下列:
table_catalog
table_schema
table_name
view_definition
check_option
is_updatable
is_insertable_into
is_trigger_updatable
is_trigger_deletable
is_trigger_insertable_into
Run Code Online (Sandbox Code Playgroud)
这对于物化视图是可能的吗?
从我目前的研究来看,物化视图似乎被故意排除在 information_schema 之外,因为
information_schema 只能显示存在于 SQL 标准中的对象。
( http://www.postgresql.org/message-id/3794.1412980686@sss.pgh.pa.us )
由于它们似乎完全被排除在 information_schema 之外,我不知道如何解决这个问题,但我想做的是双重的:
view_definition
列information_schema.views
)。postgresql materialized-view information-schema postgresql-9.4
简而言之,
哪些因素会影响查询优化器对索引视图索引的选择?
对我来说,索引视图似乎违背了我对优化器如何选择索引的理解。我之前看过这个问题,但 OP 并没有得到很好的接受。 我真的在寻找 guideposts,但我会编造一个伪示例,然后发布带有大量 DDL、输出、示例的真实示例。
假设我使用的是 Enterprise 2008+,理解
with(noexpand)
以这个伪示例为例:我创建了一个包含 22 个连接、17 个过滤器和一个跨越 1000 万行表的马戏团小马的视图。这种观点实现起来很昂贵(是的,大写 E)。我将对视图进行 SCHEMABIND 和索引。然后一个 SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84
. 在我不知道的优化器逻辑中,执行了底层连接。
结果:
那么这里发生了什么?我已经在Enterprise 2008、2008-R2 和 2012 中尝试过。根据我能想到的每个指标,使用视图索引的效率要高得多。我没有参数嗅探问题或倾斜的数据,因为这是临时的。
除非你是一个受虐狂,否则你可能不需要或不想阅读这部分。
是的
,企业版。
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 2012 年 2 月 10 日 19:39:15 …
TL;DR:我在索引视图中有一个无法修复的损坏。以下是详细信息:
跑步
DBCC CHECKDB([DbName]) WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, NO_INFOMSGS, ALL_ERRORMSGS
在我的数据库之一上产生以下错误:
消息 8907,级别 16,状态 1,第 1 行 空间索引、XML 索引或索引视图“ViewName”(对象 ID 784109934)包含不是由视图定义生成的行。这不一定表示此数据库中的数据存在完整性问题。(……)
CHECKDB 在表“ViewName”中发现 0 个分配错误和 1 个一致性错误。
repair_rebuild 是最低修复级别 (...)。
我确实理解此消息表明索引视图“ViewName”的物化数据与基础查询生成的数据不同。但是,手动验证数据不会出现任何差异:
SELECT * FROM ViewName WITH (NOEXPAND)
EXCEPT
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
EXCEPT
SELECT * FROM ViewName WITH (NOEXPAND)
Run Code Online (Sandbox Code Playgroud)
NOEXPAND
用于强制在 上使用(唯一)索引ViewName
。FORCESCAN
用于防止索引视图匹配发生。执行计划确认这两种措施都有效。
这里没有返回任何行,这意味着两个表是相同的。(只有整数和 guid 列,排序规则不起作用)。
无法通过在视图上重新创建索引或运行DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS …
我遇到了陷入僵局的情况,我想我已经缩小了罪魁祸首的范围,但我不太确定我能做些什么来解决它。
这是在运行 SQL Server 2008 R2 的生产环境中进行的。
为了让您稍微简化一下情况:
我有 3 个表,定义如下:
TABLE activity (
id, -- PK
...
)
TABLE member_activity (
member_id, -- PK col 1
activity_id, -- PK col 2
...
)
TABLE follow (
id, -- PK
follower_id,
member_id,
...
)
Run Code Online (Sandbox Code Playgroud)
该member_activity
表有一个定义为 的复合主键member_id, activity_id
,因为我只需要以这种方式查找该表上的数据。
我也有一个非聚集索引follow
:
CREATE NONCLUSTERED INDEX [IX_follow_member_id_includes]
ON follow ( member_id ASC ) INCLUDE ( follower_id )
Run Code Online (Sandbox Code Playgroud)
此外,我有一个 Schema-bound 视图network_activity
,其定义如下:
CREATE VIEW network_activity
WITH SCHEMABINDING
AS
SELECT …
Run Code Online (Sandbox Code Playgroud) sql-server ×6
postgresql ×3
view ×2
aggregate ×1
corruption ×1
dbcc-checkdb ×1
deadlock ×1
index ×1
index-tuning ×1
mysql ×1
mysql-5.6 ×1
performance ×1