oracle—使用not in sql查询时,优化此sql语句的最佳方法是什么?

8gsdolmq  于 2021-07-29  发布在  Java
关注(0)|答案(2)|浏览(616)

那张table叫 TB_ORDER 有9000万条数据记录,但只有500条状态既不是b也不是c的记录。

  1. SELECT
  2. ORDER.ID,ORDER.STATE,ORDER.NAME
  3. FROM
  4. TB_ORDER ORDER
  5. WHERE
  6. ORDER.STATE NOT IN ('B','C') ;

我的同事这样写sql,因为 full table scan 。所以我试着这样修改它。可以吗?我在状态字段上添加了索引。它还在吗 full table scan 因为子查询sql结果非常大((90000000-500)/90000000)?

  1. SELECT
  2. A.ID,A.NAME,A.STATE
  3. FROM TB_ORDER A
  4. WHERE
  5. NOT EXISTS
  6. (
  7. SELECT 1 FROM TB_ORDER B WHERE A.ID=B.ID and B.STATE='B'
  8. UNION ALL
  9. SELECT 1 FROM TB_ORDER C WHERE A.ID=C.ID and C.STATE='C'
  10. )
pprl5pva

pprl5pva1#

你真的需要那个不在里面的人吗?您可以通过使用函数然后创建基于函数的索引来解决这个问题。确保where子句与 predicate 完全匹配。例子:

  1. -- table
  2. create table t_large_table (id NUMBER GENERATED ALWAYS AS IDENTITY,state VARCHAR2(1));
  3. -- some sample data
  4. DECLARE
  5. BEGIN
  6. FOR i IN 1 .. 10 LOOP
  7. INSERT INTO t_large_table (state) VALUES ('A');
  8. INSERT INTO t_large_table (state) VALUES ('B');
  9. END LOOP;
  10. INSERT INTO t_large_table (state) VALUES ('C');
  11. INSERT INTO t_large_table (state) VALUES ('D');
  12. COMMIT;
  13. END;
  14. /
  15. -- create index with function that has a bucket to put all states that are relevant to me. In this case everything that is not A or B
  16. CREATE INDEX t_large_table_idx
  17. ON t_large_table (CASE state WHEN 'A' THEN 'A' WHEN 'B' THEN 'B' ELSE 'X' END);
  18. -- run a select with exactly same function as the index
  19. SELECT *
  20. FROM t_large_table
  21. WHERE CASE state WHEN 'A' THEN 'A' WHEN 'B' THEN 'B' ELSE 'X' END = 'X';
  22. -- check explain plan
  23. -----------------------------------------------------------------
  24. | Id | Operation | Name |
  25. -----------------------------------------------------------------
  26. | 0 | SELECT STATEMENT | |
  27. | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T_LARGE_TABLE |
  28. | 2 | INDEX RANGE SCAN | T_LARGE_TABLE_IDX |
  29. -----------------------------------------------------------------
展开查看全部
wko9yo5t

wko9yo5t2#

我给你提个建议,你可以试试。

  1. Select o.ID,o.o,o.NAME
  2. FROM TB_ORDER o
  3. Inner Join
  4. (
  5. Select STATE from
  6. (
  7. Select STATE from TB_ORDER Group by ORDER
  8. ) Q Where STATE NOT IN ('B','C')
  9. ) QQ on QQ.STATE = o.STATE

相关问题