JOIN 子句上的 SQL 排序规则问题——运行时极慢

Posted

技术标签:

【中文标题】JOIN 子句上的 SQL 排序规则问题——运行时极慢【英文标题】:SQL Collation Issue on JOIN clause -- EXTREMELY slow runtime 【发布时间】:2018-09-20 06:27:48 【问题描述】:

我正在尝试在查询中连接来自不同数据库的两个表。它们有不同的排序规则类型。主数据库具有排序规则:SQL_Latin1_General_CP1_CS_AS

我要加入的数据库具有排序规则:SQL_Latin1_General_CP1_CI_AS

当我尝试在没有排序规则的情况下运行时出现此错误(显然):

无法解决之间的排序规则冲突 “SQL_Latin1_General_CP1_CS_AS”和“SQL_Latin1_General_CP1_CI_AS”在 等于运算。

我对整理不熟悉,所以我不知道该怎么办。如果我从查询中删除第二个数据库的各个方面,它会立即运行。一旦我开始使用连接,查询就会运行一个小时以上,但没有任何结果。

如果您需要更多上下文,请告诉我。

【问题讨论】:

你能显示你正在使用的两个不同的查询吗? 您是否要以区分大小写的方式加入? 更改列的排序规则将使查询不可搜索;因此,您拥有的任何索引都将在该列上被忽略。这很可能是您的查询变得如此缓慢的原因。 @Larnu 在做了一点谷歌搜索之后,这就是我发现的。有没有解决这个问题的好方法?不幸的是,我无法真正改变表格。 @EzequielLópezPetrucci 我不在乎大小写,因为它的价值! 【参考方案1】:

正如 cmets 中所讨论的,在查询中更改列的排序规则会使语句不可 SARGable。这就是为什么您会看到性能显着下降的原因,因为您无法使用索引。

如果您需要在 2 个数据库上保持不同的排序规则,那么一种方法是添加一个 PERSISTED 计算列。然后,您可以改为在该列上添加索引。这将保持 SARGability。

如果您要保留非大小写敏感,那么您需要在区分大小写的数据库中创建计算列。我不知道您的列的名称,但是您对计算列的声明将类似于:

ALTER TABLE YourTable ADD YourColumn_CI AS YourColumn COLLATE SQL_Latin1_General_CP1_CI_AS PERSISTED;

然后您也可以在该新列上创建索引,并且您应该获得性能优势。

编辑:作为一个非常简单的示例索引:

CREATE INDEX YourColumn_CI_IX ON YourTable (YourColumn_CI ASC);

【讨论】:

我想我不明白如何在不更改表的情况下在查询中创建索引。我需要使用临时表吗? 不,根本不需要使用临时表。你不明白我的回答的哪一部分?但是,索引并不是可以简单地在 SO 的答案中教授的东西。或者是 cmets。

以上是关于JOIN 子句上的 SQL 排序规则问题——运行时极慢的主要内容,如果未能解决你的问题,请参考以下文章

sql SQL Query更改where子句中的排序规则。

sql join 与列上的多个条件

在 t-sql 中转换 nvarchar 变量的排序规则

clickhouse,数据查询与写入优化,分布式子查询优化,外部聚合/排序优化,基于JOIN引擎的优化,SQL优化案例,物化视图提速,查询优化常用经验法则,选择和主键不一样的排序键,数据入库优化(代码

JOIN 子句中的条件是邪恶的 SQL

Spark SQL 中的 where 子句与 join 子句