表设计和查询

时间:2014-06-10 23:35:43

标签: sql sql-server join

我有一个表格设计,由这个令人敬畏的手绘图像表示。

enter image description here

基本上,我有一个帐户事件,可以是交易(向第三方付款或从第三方付款)或转帐(在用户持有的帐户之间转帐)。

所有常见数据都保存在事件表(DateCreatedBySource Account Id ...)中,然后如果是事务,则会保留特定于交易的数据在帐户交易表(第三方,交易类型(DebitCredit)...)中。如果事件是转移,则转移特定数据位于account_transfer表格中Amountdestination account id ...)。

注意,我忘记绘制的内容是Event表格中有event_type_id。如果是event_type_id = 1,那么它就是交易。如果它是2,那么它就是转移

传输表和事务表都通过事件id外键链接到事件表。

请注意,交易没有金额,因为交易可以拆分为多个支付行,因此它有一个子帐户_transaction_line。为了获得交易金额,您可以将其计算在一起。

外键全部设置,主键上有索引......

我的问题是关于设计和查询。如果我想列出特定帐户的所有事件,我可以:

Select 
from Event, 
where event_type = 1 (transaction), 
then INNER join to the Transaction table,
 and INNER join to the transaction line (to sum the total)... 
 and then UNION to another selection, 
selecting 
from Event,
 where event_type = 2 (transfer),
 INNER join to transfer table... 
 and producing a list of all events.

Select 
from Event, 
then LEFT join to transaction, 
then LEFT join to transaction line,
 then LEFT join to transfer ... 
 and sum up totals (because of the transaction lines).

哪个效率更高?我认为选项1是最好的,因为它避免了LEFT连接(Scans?)

... OR

选项1的索引视图?

1 个答案:

答案 0 :(得分:0)

关于效果

对于SQL Server中的性能分析,有很多因素在起作用,例如

  • 您要运行的查询数量是多少,尤其是在相同的数据?例如,如果80%的查询大约占数据的20%,那么缓存可能会有很大帮助。 (见下面关于这可能有什么影响的设计部分)
  • 您的数据库是在同一台服务器上分发还是并置?我认为它是一个单一的服务器系统,但如果它们是分布式的,那么设计和优化可能会有所不同。
  • 这些查询是在后台进程中执行还是按需执行,而用户希望更快地获得结果?

如果没有这些(也许还有其他一些跟进问题,一旦提供了答案),给出一个比另一个更好的答案是不明智的。

话虽如此,根据我的个人经验,专门针对SQL服务器的最佳选择是使用query analyzer,这实际上是非常合理的,作为您的第一站。之后,您可以进行一些性能分析以找到最佳解决方案。通常,这些是由modeling查询流量完成的,就像系统处于常规负载时一样。 (仅供参考:建模链接是ASP.NET性能建模,但各种核心概念也适用于SQL。)您通常将系统置于负载状态,然后:

  • 查看丢失了多少连接 - 如果查询费用昂贵,这可能会增加。
  • 服务器上的性能计数器,用于查看系统如何处理负载。
  • 来自查询的响应,看看是否有人开始无法提供有效的响应,尽管这不太可能发生

仅供参考:这是基于我个人的经验,在为多个项目进行了各种类型的绩效分析之后。我们期望在我们当前的项目中再次这样做,虽然这次我们使用AD和Azure表而不是SQL,因此该方法不是特定于SQL服务器,尽管工具,流量配置文件和什么措施各不相同。

设计

在帐户交易行中引入事件ID: 虽然您没有明确说明,但似乎事件ID和事务ID在第一次输入后不会改变。如果是这种情况并且您只对获取此查询中的事务总数感兴趣,那么另一个选项(将优化您的查询)将是向AccountEvent的主键添加外键(我认为是事件id)。在最严格的数据库意义上,你对表格进行了一些规范化处理,但在实践中,它通常会对性能有所帮助。

计算插入总计: 我在过去的项目中采取的另一种方法(仅仅因为我在上个世纪使用FoxPro而FoxPro在连接时往往非常慢)是将总金额保留在主表中,相当于您的事务表。如果您的读取大大超过您的写入,这将非常有用,并且在SQL的情况下,您可以发出事务以在其他表中创建条目并同时更新总计(因此我对您的查询配置文件有疑问)。

加入交易&转移表: 保留一个值来指示哪个是哪个,并保持总数 - 与前一个相似但处于不同的水平。这将减少查询的连接数,但仍然有插入的总数 - 我更喜欢之前的这一个。

完全取消标准化: 这是人们使用的另一种方法(特别是在NOSQL空间中),但它在使用SQL Server时让我感到沮丧,所以我对它有个人偏见,但你可以很好地搜索它并找到它。