在提高count(1)
查询的性能时,数据库设计的常见/最佳做法是什么? (我目前正在使用SQLite )
我已对数据进行了规范化,它存在于多个表中,而对于我想要在具有良好索引的单个表上执行的简单操作 - 查询对于我的目的而言是可接受的。
例如:
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;
我应该如何缓存结果?什么是好的设计? 我的自然反应是添加一个表,仅用于存储每个员工的缓存结果行?
答案 0 :(得分:1)
修改强>
Command Query Responsibility Segregation
(CQRS)等设计模式专门旨在提高数据访问的read side
性能,通常是在分布式系统和企业范围内。
与CQRS通常相关的另一种模式是"Event Sourcing",它存储,然后允许“重播”命令,用于各种用例。
上述情况对您的方案可能过度,但在内部应用级别实施缓存非常简单,可以通过Sqllite Trigger
假设“读取”比写入actions
或transactions
表的次数多得多,
action
或transactions
表更新时,您都需要更新这些缓存表。一种廉价(和讨厌)的方法是在action
和transactions
表上提供INSERT,UPDATE和DELETE触发器,然后更新相应的缓存表。除了像SqlLite
这样的本地关系数据库之外,像MongoDb, Cassandra and Redis
这样的NoSql数据库经常被用作读取繁重环境中读取端缓存的替代方法(取决于您的数据类型和格式)需要缓存)。但是,您需要处理将“master”(例如SQLLite)数据库中的数据同步到这些缓存读取存储的替代方法 - 触发器显然不会在此处删除它。
原始答案
如果您100%确定您始终为同一客户重复完全相同的查询,请务必保留结果。
但是,在大多数其他情况下,RDBMS通常可以很好地处理缓存。
与查询的INTERSECT
SELECT SID from transactions where currency='USD'
如果有大量有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
您可能只是检查索引:
有关
Actions(Employee, Type)
或Actions(Employee, Type, Area)
上的索引是有意义的(假设Employee具有最高的选择性,并且取决于类型和区域的选择性)。
您还可以将其与Actions(Employee,Type,Area,SID)上的索引进行比较,作为第二个查询的覆盖索引。
对于上面的联接,您需要Transactions(SID, Currency)