【问题标题】:Stop query from checking further with "between dates" condition after all dates are found in sorted table在排序表中找到所有日期后,停止查询进一步检查“日期之间”条件
【发布时间】:2021-07-08 16:43:21
【问题描述】:

我有一个非常大的表格,其中有一列包含日期。由于表格太大,我想请求数据,例如每天,我都在尝试使用以下语句:

SELECT *
  FROM [my_db].[dbo].[my_data] where date between '2019-03-25' and '2019-03-26'

到目前为止一切顺利,当我运行此查询时,将返回相关数据(大约 10,000 行)。但是,查询并没有停止,它会持续执行很长时间(看不到多长时间,我总是在大约 30 分钟后停止)。 我认为它正在检查更合适的日期。但是,表格已排序,所以知道不会有更多日期了。

在这里处理这个问题的最佳方法是什么?在没有找到进一步的结果后,有没有办法设置某种超时?还是我应该只使用正常的超时时间并希望交易及时完成?谢谢!

【问题讨论】:

  • the table is sorted, 没有这样的东西。表中没有隐含的顺序。除非使用 ORDER BY 子句,否则不能保证结果顺序。没关系。查询性能受索引影响,而不是物理排序顺序。桌子有多大? date 是否已编入索引?如果没有,服务器将不得不扫描整个表,因为没有保证最后不会有匹配的行
  • 无论如何,当笔记本电脑可以轻松运行具有多 GB 表的数据库时,large 意味着数十亿行。对于需要 30 分钟的查询,date 未编入索引或这不是真正的查询,并且其他条件会强制进行全表扫描。 10K 行是 no 数据
  • 这意味着该字段没有被索引。它必须被索引。没有其他方法可以加速查询。没有“可能”,没有索引,服务器不知道该字段中的内容,因此它必须检查所有值。
  • 建立索引后,您可以使用多种技术来进一步提高性能。压缩表可以减少磁盘 IO,从而提高性能。数据库服务器的主要延迟是从磁盘读取,而不是从 CPU 读取,因此压缩提供了明显的好处。它也是透明的,这意味着您不必修改查询和应用程序
  • 另一种获取表中总行数的方法是在 SQL Management Studio 中打开表的“属性”窗口,然后查看“存储”页面。属性 Row count 显示总行数

标签: sql sql-server bigdata


【解决方案1】:

所以听起来您的查询正在执行table scan 来检索您的数据。

我们对您的硬件性能一无所知,但对于可能高度碎片化的大型表,这可能是在慢速驱动器上的耗时操作,或者如果 IO 是瓶颈。

您可以通过多种方式快速获取大致的行数。阅读您提到的 cmets,您是在笔记本电脑上执行此操作的,因此您可能是唯一的用户,在这种情况下,大概的计数可能会大打折扣。

最简单的就是跑

exec sp_spaceused 'tablename'

您可以查询表上的索引列表

select * from sys.indexes where object_id=Object_Id('tablename')

您还可以使用 SSMS 中的对象资源管理器详细信息查看所有表及其统计信息的列表,包括行。连接到您的服务器并从对象资源管理器的列表中展开数据库。打开 Details 面板 (F7) 并单击 Tables,将填充列表并检索行数。

您也可以在对象资源管理器中展开 Tables,展开您的特定表,然后展开 Indexes 以查看当前定义的内容。

因为您(可能)在您的 Date 列上没有索引,即使知道您已收到所有合格结果,SQL Server 没有因为它必须 扫描 表。没有索引,就无法保证一定范围内的行都将按顺序驻留。

这意味着它会直接跳入一端并开始逐页阅读,直到读到最后,检查每一行以查看它是否符合您的过滤条件。如果您期望的数据恰好位于它读取的第一页上,那么很好 - 但 SQL Server 无法知道它已找到每个可能的合格行 - 许多因素(例如页面碎片)可能意味着某些行可能会在列表中进一步存在组成表格数据的页面。

date 列上的索引将有很大帮助,因为 SQL 服务器可以搜索直接到第一个限定日期的开始并按顺序读取值直到它已到达最后一个符合条件的行,因为数据已排序,它知道它已到达末尾。

索引也有助于查询,例如select count(*)。每个索引(过滤索引除外)包括每一行,但不是每一列 - 因此,为了获得行数,SQL Server 将扫描 最窄 索引,这意味着它的 IO 可能最少。

此外,如果您实际上并不需要每一列,则执行select * 将对性能产生影响。

如果您的查询具有高度选择性,并且您在date 上有一个索引,SQL Server 将在索引中查找所需的行,然后执行 书签查找 以检索剩余的列。

然而,这是一项昂贵的操作,因此存在一个不值得权衡的阈值,SQL Server 将选择扫描表来避免查找操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2011-08-22
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多