【问题标题】:Best way to use a lookup value in SQL view?在 SQL 视图中使用查找值的最佳方法?
【发布时间】:2021-07-09 02:09:38
【问题描述】:

我需要从表中查找日期,然后使用该值过滤另一个表。这两个表没有任何关系。

这是虚拟示例设置

CREATE TABLE config (
    idp INT NOT NULL,
    eff_date DATE NOT NULL , 
    last_transaction DATE NOT NULL, 
    a VARCHAR(50) NULL
);

INSERT INTO config (idp, eff_date, last_transaction, a)
  VALUES
(1, DATE '2021-05-03', DATE '2021-05-02', 'abc')
;

CREATE TABLE transactions (
    mth_eff_date DATE NOT NULL , 
    amt INT NOT NULL 
);
CREATE INDEX transaction_date ON transactions (mth_eff_date);

INSERT INTO transactions VALUES (DATE '2021-05-02', 825);
INSERT INTO transactions VALUES (DATE '2021-05-02', 650);
INSERT INTO transactions VALUES (DATE '2021-05-02', 825);
INSERT INTO transactions VALUES (DATE '2021-05-03', 500);
INSERT INTO transactions VALUES (DATE '2021-05-03', 650);
INSERT INTO transactions VALUES (DATE '2021-05-04', 235);
INSERT INTO transactions VALUES (DATE '2021-05-06', 853);

这是我的解决方案,它在大型数据集上的性能非常差。在测试时我检查了运行时间,如果我硬编码 (SELECT last_transaction from lt) 部分并且它运行得非常快。

WITH lt AS 
  (SELECT last_transaction
    FROM config
  ),
  transactions_filt AS 
  (SELECT * 
    FROM transactions
    WHERE mth_eff_date <= (SELECT last_transaction FROM lt)
  )
  SELECT * FROM transactions_filt
;

(以上内容以fiddle的形式提供。)

最好的方法是什么?

【问题讨论】:

  • 有点猜想,但如果你做了select max(last_transaction) from lt,你可能会欺骗优化器进入使用一次性值而不是表值的计划。这可能会有所帮助,因为可能会删除 lt CTE
  • STR_TO_DATE 是 MySQL 函数,而不是 Oracle 数据库函数。请正确标记您的问题,因为您的查询的正确语法和预期的优化器行为可能会有所不同。
  • @LoztInSpace 不幸的是,这不起作用
  • 请发布查询计划。 test.config.last_transaction 上有索引吗? test.transactions.mth_eff_date 上有索引吗?
  • @wxecqz123 。 . . insert 代码仍然不兼容 Oracle,这使问题变得混乱。

标签: sql database oracle


【解决方案1】:

当查询性能不佳时,第一个响应是尝试索引相关列,在本例中为 config.last_transaction

CREATE INDEX config_last_transaction ON config (last_transaction);

使用小样本集,性能上的差异不会很明显,但在执行计划中是可见的。没有索引:

Id Operation Name Rows Bytes Cost Time
0 SELECT STATEMENT 1 22 3 00:00:01
1 TABLE ACCESS BY INDEX ROWID TRANSACTIONS 1 22 0 00:00:01
* 2 INDEX RANGE SCAN TRANSACTION_DATE 1 0 00:00:01
3 TABLE ACCESS FULL CONFIG 1 9 3 00:00:01

带索引:

Id Operation Name Rows Bytes Cost Time
0 SELECT STATEMENT 1 22 1 00:00:01
1 TABLE ACCESS BY INDEX ROWID TRANSACTIONS 1 22 0 00:00:01
* 2 INDEX RANGE SCAN TRANSACTION_DATE 1 0 00:00:01
3 INDEX FULL SCAN CONFIG_LAST_TRANSACTION 1 9 1 00:00:01

请注意,查询从使用成本为“3”的表扫描变为使用成本“1”的索引扫描。

另一种方法(不排除创建索引)是尝试编写查询的替代方法,例如连接:

SELECT t.mth_eff_date, t.amt
  FROM transactions t
    INNER JOIN config c ON t.mth_eff_date <= c.last_transaction
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多