Sql LTRIM(RTRIM(COALESCE(TextField,,))坏吗?

Sql LTRIM(RTRIM(COALESCE(TextField,,))坏吗?,sql,sql-server,performance,tsql,Sql,Sql Server,Performance,Tsql,我有一个非常高的流量表,其中有一个char50字段,它参与了几个索引。这个char50字段允许空值,在这种情况下,空值被视为与非空、零长度字符串相同 我还忽略了前导和尾随空格,虽然在插入数据之前我会清理数据,但它也可能是通过我无法控制的方式插入的 我有一个存储过程,用于将数据从一个表复制到主表,它需要高性能。我需要在插入新数据之前删除重复记录,我正在使用讨论的方法执行删除 我的delete语句如下所示: delete masterTable from masterTable t join

我有一个非常高的流量表,其中有一个char50字段,它参与了几个索引。这个char50字段允许空值,在这种情况下,空值被视为与非空、零长度字符串相同

我还忽略了前导和尾随空格,虽然在插入数据之前我会清理数据,但它也可能是通过我无法控制的方式插入的

我有一个存储过程,用于将数据从一个表复制到主表,它需要高性能。我需要在插入新数据之前删除重复记录,我正在使用讨论的方法执行删除

我的delete语句如下所示:

delete masterTable
from masterTable t
    join incomingDataTable inc on
    (
        LTRIM(RTRIM(COALESCE(inc.TextField,''))) = 
             LTRIM(RTRIM(COALESCE(t.TextField,'')))
    )
where LTRIM(RTRIM(COALESCE(t.TextField,''))) <> ''  
我喜欢像LTRIMRTRIM这样的结构。。。这些都不好。我的delete语句可以改进吗?如果可以,如何改进

编辑:只是澄清一下,TextField确实参与了两个表的索引。
EDIT2:TextField在两个表中都定义为char50。它不是文本类型。

我认为在SQL Server中,您可以将填充字符串与非填充字符串进行匹配,从而节省您在LTRIM/RTRIM上的工作量,但我不是100%这样做的


然而,整理数据是ETL的一部分,需要在数据到达目的地之前完成。您可能会在大型数据集上发现,创建数据的临时副本、重新处理数据、索引数据,然后进行所需的匹配会更快。

我认为在SQL Server中,您可以将填充字符串与非填充字符串进行匹配,从而节省您在LTRIM/RTRIM上的工作量,但我并不是100%这样做的


然而,整理数据是ETL的一部分,需要在数据到达目的地之前完成。您可能会发现,在大型数据集上,创建数据的临时副本、重新处理数据、索引数据,然后执行所需的匹配会更快。

这是不好的,因为您的联接必须扫描整个索引,这是因为您的条件不好

您还确定是文本数据类型吗?上次我检查您不能对文本数据类型列使用LTRIM或RTRIM吗

为了响应char对varchar的注释,运行以下命令

declare @v varchar(50),@v2 char(50)
select @v ='a',@v2 = 'a'

select datalength(@v),datalength(@v2)

这是不好的,因为您的加入将不得不扫描整个索引,这是因为您的条件不是

您还确定是文本数据类型吗?上次我检查您不能对文本数据类型列使用LTRIM或RTRIM吗

为了响应char对varchar的注释,运行以下命令

declare @v varchar(50),@v2 char(50)
select @v ='a',@v2 = 'a'

select datalength(@v),datalength(@v2)

我相信这个威胁是正确的

向表中添加一个INSERT/UPDATE触发器以保证该列上没有空格,怎么样

如果列为VARCHAR,SQL Server将自动忽略结尾空白。不过,前导空格仍然很重要


实际上,SQL Server在执行联接之前不会自动将这两个列填充到CHAR50吗?隐式转换。

我相信SQLMenage是正确的

向表中添加一个INSERT/UPDATE触发器以保证该列上没有空格,怎么样

如果列为VARCHAR,SQL Server将自动忽略结尾空白。不过,前导空格仍然很重要

实际上,SQL Server在执行联接之前不会自动将这两个列填充到CHAR50吗?隐式转换。

您需要:

使用表达式ltrimrtrimcaleastextfield在主表上创建计算列, 在此列上建立索引,然后 在联接中使用此列。 按照现在表的设计方式,很难使这个查询索引友好

如果无法更改表结构,但可以估计前导空格的数量,则可以使用下面介绍的方法

但是,此解决方案远不如在计算列上创建索引有效。

您需要:

使用表达式ltrimrtrimcaleastextfield在主表上创建计算列, 在此列上建立索引,然后 在联接中使用此列。 按照现在表的设计方式,很难使这个查询索引友好

如果无法更改表结构,但可以估计前导空格的数量,则可以使用下面介绍的方法


但是,这种解决方案远不如在计算列上创建索引有效。

我建议将该数据类型更改为VARCHAR50—最多10个字符,CHARx可能有意义,因为它速度稍快,开销也较小—但只有50个字符,除非所有列都被完全使用,最多50个字符,这是一个很大的开销,特别是因为此列也用于索引

将其更改为VARCHAR50可能会大大减少表所需的空间,具体取决于您的数据量和50个字符中实际使用的字符数,并且所有涉及的索引也会变得更小-此外,您不再需要这个COALESCE、LTRIM、RTRIM之类的东西:-


Marc

我建议将该数据类型更改为VARCHAR50-最高约10 c 字符,字符可能是有意义的,因为它的速度稍微快一点,开销也比较小-但是对于50个字符,除非所有列都被完全使用到50个字符,否则这是一个很大的开销,特别是因为这个列也用于索引中

将其更改为VARCHAR50可能会大大减少表所需的空间,具体取决于您的数据量和50个字符中实际使用的字符数,并且所有涉及的索引也会变得更小-此外,您不再需要这个COALESCE、LTRIM、RTRIM之类的东西:-


Marc

如果每次使用数据时都要修剪数据,那么它不应该是char数据类型,而应该是varchar数据类型。每当您每次查询字段都必须使用函数时,您的数据库设计就会出现问题

您可能会发现此讨论很有帮助:

如果每次使用数据时都要修剪数据,则不应使用char数据类型,而应使用varchar数据类型。每当您每次查询字段都必须使用函数时,您的数据库设计就会出现问题

您可能会发现此讨论很有帮助:

关于如何改进它,有什么建议吗?关于你的问题,具体来说是50。对不起,我不准确,我将编辑我的OP。如果你有前导空格,那么你可能无法改进它。您应该在表上有一个不允许前导空格的约束,这样您就不必担心以后会出现这种情况您应该使用varchar50而不是char50,除非您总是有50个字符,但是由于您正在使用RTRIM,我怀疑它是否会运行我发布的其他代码,并且您将看到char使用了所有50字节。关于如何改进它?关于你的问题,它特别是char50。对不起,我不准确,我将编辑我的OP。如果你有前导空格,那么你可能无法改进它。您应该在表上有一个不允许前导空格的约束,这样您以后就不必担心这个问题,您应该使用varchar50而不是char50,除非您总是有50个字符,但是由于您正在执行RTRIM,我怀疑它是否运行我发布的其他代码,您将看到char使用了所有50字节,或者清理数据并添加一个约束将不允许拖尾和前导空格,尽管这对正在运行的数据库来说可能是一个难题。或者清理数据并添加一个约束将不允许拖尾和前导空格,尽管这对正在运行的数据库来说可能是一个难题。您不会从我这里得到任何关于db的设计有问题的论点!我不会说db的设计有问题!