我在下面看到了SQL外观。问题是表T2太大,下载所有数据需要几个小时(虽然显示前500个结果需要7秒)。有没有人知道如何加速" NOT IN"条款,或替换" NOT IN"通过其他排除方法?非常感谢你!
SELECT *
FROM T1
WHERE NVL(T1.A,'1') NOT IN (SELECT B FROM T2)
答案 0 :(得分:3)
您可以使用T1
和T2
表之间的联接来重新定义查询:
SELECT *
FROM T1
LEFT JOIN T2
ON NVL(T1.A, '1') = T2.B
WHERE T2.B IS NULL
如果您在连接列上有索引,特别是T2
的{{1}}列上的索引,这可能会加快速度。
答案 1 :(得分:0)
如果表T1
的记录数量非常少和,如果表格T2
在列B
上有索引,那么您所需的访问计划是对T2
中的每条记录T1
执行一次索引查找。
预期执行计划使用 NESTED LOOP ANTIJOIN 。
如果需求已完整且优化程序统计信息是新的,则Oracle将自动选择此计划 - 您无需在其他答案中重新构建查询。
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 130 | 106 (0)| 00:00:02 |
|* 1 | FILTER | | | | | |
| 2 | NESTED LOOPS ANTI SNA| | 100 | 2600 | 106 (4)| 00:00:02 |
| 3 | TABLE ACCESS FULL | T1 | 100 | 1300 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | T2_IDX | 1 | 13 | 1 (0)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | T2 | 4236 | 55068 | 4 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( NOT EXISTS (SELECT 0 FROM "T2" "T2" WHERE "B" IS NULL))
4 - access("B"=NVL("T1"."A",1))
5 - filter("B" IS NULL)
此执行计划的问题在于,它与T1
中行的行数一致,即如果T1
很大(M行),则查询将停止表演。在这种情况下,所需的访问权限是在每个表上进行一次全扫描。
预期计划为 HASH ANTIJOIN
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 2600 | 5479 (1)| 00:01:38 |
|* 1 | HASH JOIN ANTI NA | | 100 | 2600 | 5479 (1)| 00:01:38 |
| 2 | TABLE ACCESS FULL| T1 | 100 | 1300 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 84722 | 1075K| 5476 (1)| 00:01:38 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"=NVL("T1"."A",1))
最后注意事项 - 您在条件中使用NVL(T1.A,'1')
- 值是' 1'表T2
中是否存在?如果知道并且不变,则可以简单地在T1
中包含或排除T2
的所有NULL值,而无需查找df['w2v_sim']=df.apply(lambda x: w2v.n_similarity(x.q1, x.q2), axis=1)
。
答案 2 :(得分:0)
感谢大家的帮助。 更多背景: 1. T1和T2都有索引 2. T2的值为'1',但这不是我们想要的。我们使用NVL(“T1”。“A”,1)的原因是因为我们希望在最终结果的A列中保留空值记录。
所以,我修改了如下的查询,速度更快,运行和下载只需10分钟。
WITH T3 AS(从T2选择DISTINCT B)
SELECT T1。*
来自T1左接点T3上T1.A = T3.B
T3在哪里。 B IS NULL且T1.A不为空
UNION ALL
SELECT T1。*
T1.A IS NULL