隐式转换会破坏SQL查询性能吗?

chuttersnapUnsplash拍摄的照片
YouTube上观看此帖子

即使您已经为其创建了索引,您是否遇到过运行缓慢的查询?

发生这种情况有几种不同的原因。 我最常看到的是以下情况。

请给我一杯意式浓缩咖啡

假设我有一个dbo.Coffee表 ,它是我的咖啡豆库存和每周从我最喜欢的绿色咖啡豆供应商处获取的价格。 看起来像这样:

-- Make sure Actual Execution Plan is on
-- Let's see what our data looks like
SELECT * FROM dbo.CoffeeInventory
如果您想继续,可以从GitHub Gist获取此数据集

我希望能够高效地查询此表并按价格进行过滤,因此接下来我创建一个索引,如下所示:

CREATE CLUSTERED INDEX CL_Price ON dbo.CoffeeInventory (Price)

现在,我可以编写查询来找出哪些咖啡价格低于我的支付意愿:

SELECT Name, Price FROM dbo.CoffeeInventory WHERE Price < 6.75

您会希望此查询快速运行,并使用聚簇索引查找,对吗?

错误!

有没有搞错?

在谓词中要过滤的列上添加聚簇索引时,为什么SQL会扫描表? 那不是应该的工作方式!

亲爱的读者,如果我们稍微看一下表扫描操作,就会发现一些叫做CONVERT_IMPLICIT的东西:

CONVERT_IMPLICIT:快速查询的破坏者

CONVERT_IMPLICIT在做什么? 顾名思义,它必须在执行查询时转换一些数据(与我在查询中指定了显式CAST()或CONVERT()函数相反)。

之所以需要这样做,是因为我将Price列定义为VARCHAR(5):

谁将数字数据放入字符串数据类型? 今天还没有喝咖啡的人。

但是,在我的查询中,我正在对WHERE Price < 6.75的数字进行比较。 SQL Server表示不知道如何将字符串与数字进行比较,因此必须将VARCHAR字符串转换为NUMERIC(3,2)。

真痛苦

为什么? 因为SQL正在对表中的每一行执行到数字数据类型的隐式转换。 因此,它无法寻求使用索引,因为它最终必须扫描整个表才能将每个记录首先转换为数字。

这不仅发生在数字和字符串转换上。 Microsoft已发布了完整的图表,详细说明了哪些类型的数据类型比较将强制进行隐式转换:

https://docs.microsoft.com/zh-cn/sql/t-sql/data-types/data-type-conversion-database-engine

那是很多橙色圆圈/隐式转换!

如何更快查询咖啡?

在这种情况下,我们有两个选择。

  1. 修复表的数据类型,使其与实际存储在此表中的数据对齐(数据管家喜欢此表)。
  2. 不会导致SQL Server转换列中的每一行。

上面的数字1是不言而喻的,如果可以的话,是更好的选择。 但是,如果您无法修改列类型,则最好像这样编写查询:

SELECT Name, Price FROM dbo.CoffeeInventory WHERE Price < '6.75'

由于我们进行了等效数据类型的比较,因此SQL Server不需要进行任何转换,就可以使用索引。 呜呜!

那我的服务器其余部分呢?

还记得上面的图表吗? 有许多不同的数据比较可能会迫使SQL Server进行痛苦的列侧隐式转换。

幸运的是, Jonathan Kehayias编写了出色的查询,可通过查询计划缓存来帮助您查找列侧隐式转换。 运行他的查询是识别查询中发生的大多数隐式转换的好方法,因此您可以返回并修复它们,然后为改进的查询性能感到高兴!

还在读书吗? 您可能会喜欢 在Twitte r 上关注我

喜欢这篇文章吗? 请通过在 下面 给它一个绿色的心 recommend来推荐它

From: https://hackernoon.com/are-implicit-conversions-killing-your-sql-query-performance-70961e547f11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值