我有一个非常高流量的表,其中char(50)
字段包含多个索引。这个char(50)
字段允许NULLS,在这种情况下,NULL值被认为与我的非NULL,零长度字符串相同。
我也忽略了领先&尾随空格,虽然我在插入数据之前擦除了数据,但它也可以通过我无法控制的方式插入。
我有一个用于将数据从一个表复制到主表的sproc,它需要具有高性能。我需要在插入新数据之前删除重复记录,并且我正在使用所讨论的方法in this thread来执行删除。
我的删除语句如下(简化):
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,''))) <> ''
I have read构造像LTRIM(RTRIM(...))是不好的。我的删除声明可以改进,如果是,如何改进?
编辑:为了澄清,TextField
确实参与了两个表的索引。
EDIT2: TextField
在两个表中定义为char(50)
。它不是TEXT
类型。
答案 0 :(得分:8)
你需要:
masterTable
在LTRIM(RTRIM(COALESCE(TextField,'')))
上创建计算列
现在设计表的方式使得这个查询对索引友好是不可能的。
如果您无法更改表格结构但可以估算LEADING
个空格的数量,则可以使用here所述的方法。
然而,这个解决方案远不如在计算列上创建索引那么有效。
答案 1 :(得分:4)
这很糟糕,因为你的JOIN必须扫描整个索引,这是因为你的条件不是 SARGable
您是否也确定是TEXT数据类型?最后我检查过你不能对Text数据类型列使用LTRIM或RTRIM吗?
响应对varchar注释的char,运行此
declare @v varchar(50),@v2 char(50)
select @v ='a',@v2 = 'a'
select datalength(@v),datalength(@v2)
答案 2 :(得分:3)
我建议将该数据类型更改为VARCHAR(50) - 最多约10个字符,CHAR(x)可能有意义,因为它更快并且开销更少 - 但是有50个字符,除非所有列都完全最多使用50个字符,这是一个主要的开销,特别是因为此列也用于索引。
将其更改为VARCHAR(50)可能会显着减少表所需的空间(取决于您的数据量以及实际使用的50个字符中的多少),并且所涉及的所有索引也会得到很多更小 - 再加上你不再需要这个COALESCE,LTRIM,RTRIM东西: - )
马克
答案 3 :(得分:2)
我认为在SQL Server中你可以将填充字符串与非填充字符串相匹配,从而节省了自己在LTRIM / RTRIM上的工作量,但是我不是100%...
但是,整理数据是ETL的一部分,需要在数据到达目的地之前完成。您可能会在大型数据集上发现创建数据的临时副本,重新处理,索引,然后执行所需的匹配更快。
答案 4 :(得分:2)
我相信SQLMenace是正确的。
如何向表中添加 INSERT / UPDATE触发器以确保该列上没有空格?
如果列是VARCHAR,SQL Server将自动忽略结束空格。虽然领先的空白仍然很重要。
实际上,在执行JOIN之前,SQL Server是否会自动将两列填充到CHAR(50)? (牵连转换。)
答案 5 :(得分:2)
如果每次使用时都必须修剪数据,那么这不应该是char数据类型,而是varchar数据类型。每次查询字段时都必须使用函数,数据库设计出现问题。
您可能会发现此讨论很有帮助: Is the CHAR datatype in SQL obsolete? When do you use it?