你会如何优化这个查询
How would you optimize this query
我在 VFP9(是的,我知道)下一个查询完美运行,但是使用大小为 20mb(或 9k 行)的 DBF(Table)在游标上创建临时大于 2gb 的文件(这会使 VFP9 崩溃,因为它是 32 位)
SELECT DISTINCT t1.*;
FROM t1,t2;
WHERE ALLTRIM(t1.name) = ALLTRIM(t2.name);
AND ALLTRIM(t1.name2) = ALLTRIM(t2.name2);
AND t1.tyc = t2.tyc;
AND t1.nc = t2.nc;
AND t1.forced = 0;
AND t1.secuence NOT in (Select secuence FROM t2);
Into Cursor cursordel
我只放这段代码是因为行得通,除非我有超过 2k 行
我认为用连接替换“不在”可以解决问题,但没有奏效,或者至少我尝试过的方式没有奏效...
这看起来你可以做一个内部连接,我不知道 fox pro 如何处理游标中的交叉连接听起来交叉连接在这里造成了损害:9,000 行在 20mb 未修剪的交叉连接远远超过 2 GB,但听起来这可能有帮助:
SELECT;
DISTINCT t1.*;
FROM t1;
inner join t2 on
ALLTRIM(t1.name) = ALLTRIM(t2.name)
AND ALLTRIM(t1.name2) = ALLTRIM(t2.name2)
AND t1.tyc = t2.tyc
AND t1.nc = t2.nc
AND t1.forced = 0
AND t1.secuence NOT in (Select secuence FROM t2)
Into Cursor cursordel
假设第一个 table 没有重复项,我会将其表述为 not exists
:
SELECT t1.*
FROM t1
WHERE NOT EXISTS (SELECT 1
FROM t2
WHERE ALLTRIM(t1.name) = ALLTRIM(t2.name) AND
ALLTRIM(t1.name2) = ALLTRIM(t2.name2) AND
t1.tyc = t2.tyc AND
t1.nc = t2.nc
) AND
t1.forced = 0 AND
NOT EXISTS (SELECT 1
FROM t2
WHERE t2.secuence = t1.secuence
);
然后对于此查询,您需要 t2(tyc, nc, name, name2)
和 t2(secuence)
上的索引。我怀疑 t1(forced)
上的索引是否有帮助,除非该列很少 0
.
即使没有索引,这也消除了外部 SELECT DISTINCT
。
请注意,您在 t2
上的 NOT IN
情况看起来很可疑。为什么它也不需要匹配条件?
为什么首先需要 distinct?当您只想执行 EXISTS 检查时,为什么要创建隐式交叉连接然后进行过滤?而且,那些 alltrim() 的目的是什么?您的字段是否有前导空格?还是您的意思是 trim 尾随空格?如果是后者,则完全没有必要,并且还会阻止使用可能存在的索引。
SELECT * ;
FROM t1 ;
WHERE t1.forced = 0 ;
and EXISTS (select * from t2 ;
where t1.name == t2.name ;
AND t1.name2 == t2.name2 ;
AND t1.tyc == t2.tyc ;
AND t1.nc == t2.nc ) ;
and not EXISTS (select * from t2 where t1.secuence = t2.secuence) ;
Into Cursor cursordel ;
NOFILTER
我在 VFP9(是的,我知道)下一个查询完美运行,但是使用大小为 20mb(或 9k 行)的 DBF(Table)在游标上创建临时大于 2gb 的文件(这会使 VFP9 崩溃,因为它是 32 位)
SELECT DISTINCT t1.*;
FROM t1,t2;
WHERE ALLTRIM(t1.name) = ALLTRIM(t2.name);
AND ALLTRIM(t1.name2) = ALLTRIM(t2.name2);
AND t1.tyc = t2.tyc;
AND t1.nc = t2.nc;
AND t1.forced = 0;
AND t1.secuence NOT in (Select secuence FROM t2);
Into Cursor cursordel
我只放这段代码是因为行得通,除非我有超过 2k 行 我认为用连接替换“不在”可以解决问题,但没有奏效,或者至少我尝试过的方式没有奏效...
这看起来你可以做一个内部连接,我不知道 fox pro 如何处理游标中的交叉连接听起来交叉连接在这里造成了损害:9,000 行在 20mb 未修剪的交叉连接远远超过 2 GB,但听起来这可能有帮助:
SELECT;
DISTINCT t1.*;
FROM t1;
inner join t2 on
ALLTRIM(t1.name) = ALLTRIM(t2.name)
AND ALLTRIM(t1.name2) = ALLTRIM(t2.name2)
AND t1.tyc = t2.tyc
AND t1.nc = t2.nc
AND t1.forced = 0
AND t1.secuence NOT in (Select secuence FROM t2)
Into Cursor cursordel
假设第一个 table 没有重复项,我会将其表述为 not exists
:
SELECT t1.*
FROM t1
WHERE NOT EXISTS (SELECT 1
FROM t2
WHERE ALLTRIM(t1.name) = ALLTRIM(t2.name) AND
ALLTRIM(t1.name2) = ALLTRIM(t2.name2) AND
t1.tyc = t2.tyc AND
t1.nc = t2.nc
) AND
t1.forced = 0 AND
NOT EXISTS (SELECT 1
FROM t2
WHERE t2.secuence = t1.secuence
);
然后对于此查询,您需要 t2(tyc, nc, name, name2)
和 t2(secuence)
上的索引。我怀疑 t1(forced)
上的索引是否有帮助,除非该列很少 0
.
即使没有索引,这也消除了外部 SELECT DISTINCT
。
请注意,您在 t2
上的 NOT IN
情况看起来很可疑。为什么它也不需要匹配条件?
为什么首先需要 distinct?当您只想执行 EXISTS 检查时,为什么要创建隐式交叉连接然后进行过滤?而且,那些 alltrim() 的目的是什么?您的字段是否有前导空格?还是您的意思是 trim 尾随空格?如果是后者,则完全没有必要,并且还会阻止使用可能存在的索引。
SELECT * ;
FROM t1 ;
WHERE t1.forced = 0 ;
and EXISTS (select * from t2 ;
where t1.name == t2.name ;
AND t1.name2 == t2.name2 ;
AND t1.tyc == t2.tyc ;
AND t1.nc == t2.nc ) ;
and not EXISTS (select * from t2 where t1.secuence = t2.secuence) ;
Into Cursor cursordel ;
NOFILTER