2010-09-22 102 views
1

当涉及到提高count(1)查询的性能时,数据库设计的常见/最佳实践是什么? (我目前正在使用SQLiteSQL数据库设计 - 缓存表?

我已经规范化了我的数据,它存在于多个表中,并且我想对具有良好索引的单个表执行简单的事情 - 查询可接受的快我的目的。

如:

SELECT count(1) from actions where type='3' and area='5' and employee='2533'; 

但是当我开始进入多表查询,事情变得太慢(> 1秒)。

SELECT count(1) 
    from 
    (SELECT SID from actions 
     where type='3' and employee='2533' 
    INTERSECT 
    SELECT SID from transactions where currency='USD') x; 

我该如何缓存我的结果?什么是好设计? 我的自然反应是添加一个表,仅用于存储每位员工的缓存结果行?

回答

1

编辑

Command Query Responsibility Segregation (CQRS)设计模式专门着眼于提高数据访问的性能read side,经常在分布式系统和企业规模。

  • 发出命令,以指示“交易”或“改变/更新”到数据
  • 当系统处理这些命令(例如,通过更新数据库表),则受影响的对象的新状态是“广播”
  • 感兴趣的系统(例如用户界面或可查询的REST API)将订阅这些数据更改,然后将更新后的数据“整形”为其特定需求
  • 然后将更新的数据缓存称为“读取商店”)

通常与CQRS相关的另一种模式是"Event Sourcing",它存储并允许各种用例的“重放”命令。

以上可能是矫枉过正的情况,但在内部应用水平非常简单的实现缓存,可通过Sqllite Trigger

假设有更多的“读”比写入您actionstransactions表,

  • 你可以创建一个特定的缓存表的“SID的行动按类型的员工,一个针对‘SID通过货币交易’,甚至将两者结合起来(取决于你有什么其他场景用于查询)
  • 然后,每次更新底层的actiontransactions表时,您都需要更新这些缓存表。一种便宜(并且令人讨厌)的方式是在actiontransactions表上提供INSERT,UPDATE和DELETE触发器,然后该表将更新适当的缓存表。
  • 您的“查询”接口现在主要使用“派生”数据(如计数)与缓存表进行交互。
  • 但是,您仍然需要处理缓存未命中情况,例如这些缓存表的初始“种子”,或者是否需要重新生成缓存表。

除了像SqlLite本地关系数据库,NoSQL数据库一样MongoDb, Cassandra and Redis经常被用作替代品读重环境(取决于你需要缓存中的数据的类型和格式)来读取端缓存。但是,您需要处理替代方法,以将来自“主”(例如SQLLite)数据库的数据同步到这些缓存读取存储 - 触发器显然不会在此处将其切断。

原来的答案

如果你是100%肯定,你总是重复一模一样的查询相同的客户,当然,坚持的结果。

但是,在大多数其他情况下,RDBMS通常会很好地处理缓存。如果有大量的与美元的交易记录

与查询

SELECT SID from transactions where currency='USD' 

相交可能是有问题的。

可能你可以用连接代替它?

SELECT count(1) from 
(
    SELECT t.[SID] 
    from 
     transactions as t 
     inner join 
     (
      SELECT SID from actions where type='3' and employee='2533' 
     ) as a 
     on t.SID = a.SID 
    where t.currency= 'USD' 
) as a 

你可能只是检查但是您的索引:

对于

  • SELECT COUNT(1)动作,其中 类型= '3' 和面积= '5' 和 员工= '2533'
  • SELECT SID从动作,其中 类型= '3' 和雇员= '2533'

Actions(Employee, Type)Actions(Employee, Type, Area)上的索引是合理的(假定Employee具有最高的选择性,并且取决于Type和Area的选择性)。

您也可以将它与Actions(Employee,Type,Area,SID)上的索引作为第二个查询的覆盖索引进行比较。

而对于以上加入,您需要索引Transactions(SID, Currency)