dat*_*000 4 sql-server query-performance
我有一个查询,它只从一张表和一个WHERE
过滤器中进行选择。然而,它需要很长时间来执行,甚至偶尔会超时。这可能是因为它从 1300 万行(其他 900 万条记录早于 2019 年)的表中过滤掉了大约 400 万行,并且它返回了所有列,其中有 101 列(混合了datetime
、varchar
, 和int
列)。它有两个索引,一个聚集在其主键上interaction_id
的索引,和一个非聚集索引,interaction_date
其上的日期时间列是主过滤器。这是查询:
SELECT *
FROM [Sales].[dbo].[Interaction]
WHERE
year(Interaction_date) >= 2019
Run Code Online (Sandbox Code Playgroud)
通过添加/调整索引或调整查询本身,我可以做些什么来提高此查询的性能?在我进入 ETL 过程或反击需要此查询的组之前(他们是一个 Hadoop sqooping 团队,他们坚持认为他们需要一直使用所有列对所有这些记录进行 sqoop),我想看看我是否作为 DBA,我可以通过做一些事情来让人们更轻松。
默认情况下,查询计划会忽略我在interaction_date
列上的非聚集索引,并且仍然执行完整的聚集索引扫描。所以我然后尝试通过包含WITH (INDEX(IX_Interaction_Interaction_Date))
在选择中来强制它使用它。
这迫使它以非聚集索引的索引扫描开始进入查询计划,估计行数为 400 万,但估计行读取为所有 1300 万。然后在很短的时间之后,它会将剩余的执行时间花在主聚集索引的键查找上。
但最终,它似乎根本没有加快查询速度。
Dav*_*oft 14
通过添加/调整索引或调整查询本身,我可以做些什么来提高此查询的性能?
是的。首先使谓词sargable。
SELECT * FROM
[Sales].[dbo].[Interaction]
WHERE Interaction_date >= '20190101'
Run Code Online (Sandbox Code Playgroud)
然后考虑分区,或包含列的过滤索引。但即使您有一个索引可以支持此查询作为简单的搜索+扫描,将所有列发送到客户端也需要时间。
Nza*_*all 10
注意:我不打算对查询本身发表评论,但考虑到此查询的大小,我将讨论一些也会对此产生影响的内容。
一些基本的数学计算,假设 varchar 列中数据的平均大小为 30 个字符,并且列大致分为 3 种类型:
101 列 * ((30+8+4)/3) = 每列 14 字节 * 4,000,000 行 = 大约 56 亿字节
略多于 5 GB 的空间,仅用于数据(以全尺寸传输大约需要 86,500 个 UDP 数据包)。考虑到每列的平均字节数可能明显高于 14 字节,这可能是一个保守的估计。每列每增加一个平均字节,就需要额外增加 400 MB 的数据传输。
根据您的连接并假设没有其他流量的直接连接,这将需要 40 秒(假设为千兆以太网)到 400 秒,或几乎 7 分钟,使用 100Mbit 以太网纯粹用于此数据。任何额外的延迟、线路上的数据流量或其他干扰也会影响所需的时间。
我知道您的客户正在使用 Hadoop 和 Sqoop,但我说的是连接的物理限制,而软件对此无能为力。查询花费的大部分时间完全有可能只是将它从您的 SQL 服务器获取到您的 Hadoop 系统。您可以通过尝试手动将 5.6 GB 文件从 SQL 服务器复制到运行 Hadoop 的任何设备来检查这有多大影响。这将很好地估计您的查询从 SQL 机器移动到 Hadoop 机器所需的时间。
归档时间: |
|
查看次数: |
1991 次 |
最近记录: |