考虑此查询:
select
map,line,pda,item,qty,qty_gift,pricelist,price,linevalue,vat,
vat_value,disc_perc,disc_value,dt_disc_value,netvalue,imp_qty,
imp_value,exp_qty,exp_value,price1,price2,price3,price4,
justification,notes
from appnameV2_Developer.dbo.pt
where exists (select 1 from [dbo].[dt] dt
where pt.map=dt.map and dt.pda=pt.pda and dt.canceled=0)
except
select
map,line,pda,item,qty,qty_gift,pricelist,price,linevalue,vat,
vat_value,disc_perc,disc_value,dt_disc_value,netvalue,imp_qty,
imp_value,exp_qty,exp_value,price1,price2,price3,price4,
justification,notes
from appnameV2_Developer_reporting.dbo.pt
我这样做是为了确保复制发布者数据库(appnameV2_Developer)和其订阅者数据库(appnameV2_Developer_reporting)在同一表(pt)中没有数据差异。特定的复制文章在dt上有一个半联接。
dt是带有PK(map,pda)的事务头表
pt是带有PK(地图,pda,线)的交易明细表
因此,我们有一个Right Semi Join合并联接。我希望它的结果按(map,pda,line)排序。但是然后,调用了(map,pda,line)上的排序运算符。
为什么会发生这种排序(或更准确地说:为什么此时尚未对数据进行排序)?查询优化器是否缺少“合并合并然后其输出(仍)按连接谓词排序”的逻辑?我想念什么吗?
答案 0 :(得分:0)
因为它决定使用“合并联接”来执行EXCEPT
子句。为了执行合并联接,两个数据集必须具有相同的顺序。
问题是,内部合并联接(在EXCEPT之前)基于表dt
,而不是基于pt
。因此,结果行将与EXCEPT
的另一边(基于pt
的顺序不同)。
为什么SQL Server会这样做?不清楚。我会做不同的。也许统计数据没有更新。也许只有很少的行对策略没有太大影响。
答案 1 :(得分:0)
第一次合并的结果将按import timeit
setup = '''
import pandas as pd
import numpy as np
def val():
v = np.random.normal(0, 0.2)
return v if 0 <= v <= 1 else 0
def gen_sentence(fdf, s):
return fdf.columns[np.random.random(len(fdf.columns)) < fdf.loc[s]]
n = 500
m = 100
fdf = pd.DataFrame([[val() for _ in range(n)] for _ in range(m)])
fdf = fdf.join(pd.DataFrame({"s": [i for i in range(m)]}))
fdf = fdf.set_index("s")
fdf.columns = ["w%d" % i for i in range(n)]
'''
test = "x = np.random.randint(0, m); gen_sentence(fdf, x)"
print(timeit.timeit(test, setup=setup, number=5000))
排序。但是,您自己提到了连接谓词,并且此第一次合并的连接谓词仅基于map, pda, line
(它们是map, pda
子句内部的谓词,除了exists
包含下推至索引扫描)。输入所有首先 required 并按cancelled
和map
进行排序,因此,这是保证该数据唯一的排序顺序,就查询的其余部分而言有关。
但是,正如我们所知,第一次合并的输出实际上是由pda
附加排序的输入得出的。看来优化器当前无法发现这种情况。优化的顺序可能意味着永远不可能意识到这种情况。因此,目前,它引入了额外的排序方式。