在某个应用程序中,我必须不断查询可能在最后插入的行中的数据。由于该表将增长很多,我想知道是否有一种标准方法可以通过使查询在表的末尾开始查找来优化查询。我认为如果数据库以类似堆栈的结构存储表的数据,我会得到相同的优化,因此将首先搜索最后插入的行。
10 回答
SQL 规范没有提到任何关于维护插入顺序的内容。实际上,大多数体面的数据库也不维护它。然后它停在这里。首先对表格进行排序不会使其更快。只需索引感兴趣的列(至少是您在 中使用的列WHERE
)。
没有标准的方法。
在某些数据库中,您可以指定索引的排序顺序。
SQL Server允许您在索引上编写 ASC 或 DESC:
[ 升序 | 描述]
确定特定索引列的升序或降序排序方向。默认值为 ASC。
在MySQL中,您还可以在创建索引时编写 ASC 或 DESC,但目前这被忽略了。它可能会在未来的版本中实现。
适当的 RDBMS 的“原则”之一是此类问题不应该涉及您或使用数据库的任何其他人。
数据库引擎可以“免费”使用它想要存储/检索记录的任何方法,因此如果您想强制执行“顶级”行为,请执行其他建议:向表(或表)添加时间戳字段,添加索引在其上并使用它作为排序和/或查询条件进行查询(例如:您每分钟轮询表,并要求时间戳> = systime-1分钟的记录)
在表格中添加计数器或时间字段,对其进行排序并获取顶部行。
换句话说:您应该忘记默认情况下以任何特定顺序访问 SQL 表的想法。seqscan 并不意味着首先搜索最旧的行,只是检查所有行。如果您想优化某些搜索,您可以在某些字段上添加索引。您正在寻找的可能是索引。
- 如果您的数据已编入索引,则无关紧要。该索引正在执行二进制搜索,而不是顺序扫描。
- 除非你正在做
TOP 1
(或类似的事情),SELECT
否则无论如何都必须扫描整个表或索引。
如果您有足够多的行使其实际上成为问题,并且您知道“最近插入的行”应该是多少,您可以尝试一种迂回的方法。
注意:即使对于相当大的表,这也不太有效,但是一旦你的主表变得足够大,我已经看到这项工作对面向用户的性能产生了奇迹。
创建一个完全模仿表结构的“临时”表。每当您插入主表时,也要插入您的“暂存”区域。当达到任意最大值的新行(例如,10,000 或任何您的限制)时,使用触发器删除表中最低id 行,将您的“暂存”区域限制为n行。
然后,查询可以首先访问那个较小的表以查找信息。由于该表被任意限制为最后n行,因此它只查看最近的数据。仅当无法找到匹配项时,您的查询(实际上,此时由于决策制定的存储过程)才会命中您的主表。
一些陷阱:
1) 确保您的触发器设置正确,以保持“主”表和“暂存”表之间的正确并发。
2) 如果处理不当,这可能很快成为维护的噩梦——并且根据您的情况,它会有点挑剔。
3)我不能强调这仅在非常特定的情况下才有效/有用。如果您的不匹配,请使用其他答案之一。
ISO/ANSI 标准 SQL 根本不考虑优化。例如,广泛认可的CREATE INDEX
SQL DDL 没有出现在标准中。这是因为标准没有对底层存储介质做任何假设,也不应该做任何假设。我经常使用 SQL 来查询文本文件和 Excel 电子表格中的数据,它们都没有任何数据库索引的概念。
你不能这样做。
但是,有一种方法可以做得更好。根据表的设计,您应该能够创建一个索引,以使事物几乎保持条目顺序。例如,如果您采用创建自动递增的 id 字段的常见做法,那么该索引几乎是按时间顺序排列的。
一些 RDBMS 允许您声明一个向后索引,即下降而不是上升的索引。如果您在 ID 字段上创建一个向后索引,并且如果优化器使用该索引,它将首先查看最近的条目。这将为您提供第一行的快速响应。
下一步是让优化器使用索引。您需要使用解释计划来查看索引是否正在使用。如果您按 id 降序查询行,优化器几乎肯定会使用向后索引。如果没有,您可以使用提示来指导优化器。
如果您仍然需要避免读取所有行以避免浪费时间,您可以使用 LIMIT 功能声明您只需要,比如 10 行,不多,或者 1 行,不多。那应该这样做。
祝你好运。
如果您的表格有创建日期,那么我会按此进行反向排序并获得前 1 个。