g.d*_*d.c 12 performance index firebird
我正在优化工作票的 Firebird 2.5 数据库。它们存储在一个声明如下的表中:
CREATE TABLE TICKETS (
TICKET_ID id PRIMARY KEY,
JOB_ID id,
ACTION_ID id,
STATUS str256 DEFAULT 'Pending'
);
Run Code Online (Sandbox Code Playgroud)
我通常想找到第一张尚未处理且处于Pending
状态的票证。
我的处理循环是:
Pending
Complete
没有什么太花哨的。如果我在这个循环运行时观察数据库,我会看到每次迭代的索引读取次数增加。据我所知,性能似乎并没有严重下降,但是我正在测试的机器非常快。但是,我从我的一些用户那里收到了性能随时间下降的报告。
我在 上有一个索引Status
,但它似乎仍然在Ticket_Id
每次迭代时向下扫描列。好像我忽略了一些东西,但我不确定是什么。像这种预期的索引读取次数是否会不断攀升,还是索引在某些方面表现不佳?
-- 编辑评论 --
在 Firebird 中,您可以限制行检索,例如:
Select First 1
Job_ID, Ticket_Id
From
Tickets
Where
Status = 'Pending'
Run Code Online (Sandbox Code Playgroud)
因此,当我说“第一”时,我只是要求它提供一个有限的记录集,其中Status = 'Pending'
.
随着时间的推移,由于处于“完成”状态的项目数量增加,会发生降级。想一想 - 测试时您不会遇到任何性能下降,因为您可能有少量状态为“完成”的行。但在生产中,它们可能有数百万行处于“完成”状态,并且这个数字会随着时间的推移而增加。从本质上讲,这会使您的 Status 索引随着时间的推移越来越没有用处。因此,数据库可能只是决定,因为 Status 几乎总是具有值“Complete”,所以它只会扫描表而不是使用索引。
在 SQL Server(也许还有其他 RDBMS?)中,可以使用过滤索引来解决这个问题。在 SQL Server 中,您可以在索引定义的末尾添加一个 WHERE 条件,表示“仅将此索引应用于 Status <> 'Complete' 的记录”。那么使用此谓词的任何查询很可能会在未设置为“完整”的少量记录上使用索引。但是,根据此处的文档:http://www.firebirdsql.org/refdocs/langrefupd25-ddl-index.html,Firebird看起来并不支持过滤索引。
解决方法是将“完整”记录放入 ArchiveTickets 表中。创建一个与 Tickets 表具有完全相同定义(尽管没有任何自动生成的 ID)的表,并通过将“Complete”记录推送到 ArchiveTickets 表来维护它们之间的行。Tickets 表上的索引将包含更少数量的记录,并且性能更高。这可能意味着您需要更改引用“完整”票证的任何报告等,以指向存档表或在票证和 ArchiveTickets 之间执行 UNION。这样做的优点不仅是速度快,而且还意味着您可以为 ArchiveTickets 表创建特定索引,以使其对其他查询执行得更好(例如:给我完整票证的平均完成时间),这些查询是Tickets 表中不需要。
如果您的生产将进入数千行,您应该关注这一点。性能会随着时间的推移而下降,并对您的用户体验产生负面影响。