我正在尝试加速我几年前为我的雇主的购买授权应用程序编写的代码。基本上我有一个SLOW子查询,我想用JOIN替换(如果它更快)。
当导演登录应用程序时,他会看到他尚未授权或拒绝的购买请求列表。使用以下查询生成该列表:
SELECT * FROM SA_ORDER WHERE ORDER_ID NOT IN
(SELECT ORDER_ID FROM SA_SIGNATURES WHERE TYPE = 'administrative director');
sa_order中只有大约900条记录,sa_signature中只有1800条记录,此查询仍需要大约5秒钟才能执行。我已经尝试使用LEFT JOIN来检索我需要的记录,但是我只能在sa_signature中获得没有匹配记录的sa_order记录,并且我需要sa_order记录“没有与'行政总监'类型的匹配记录”。非常感谢您的帮助!
两个表的架构如下:
所涉及的表格具有以下布局:
CREATE TABLE sa_order
(
`order_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`order_number` BIGINT NOT NULL,
`submit_date` DATE NOT NULL,
`vendor_id` BIGINT NOT NULL,
`DENIED` BOOLEAN NOT NULL DEFAULT FALSE,
`MEMO` MEDIUMTEXT,
`year_id` BIGINT NOT NULL,
`advisor` VARCHAR(255) NOT NULL,
`deleted` BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE TABLE sa_signature
(
`signature_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`order_id` BIGINT NOT NULL,
`signature` VARCHAR(255) NOT NULL,
`proxy` BOOLEAN NOT NULL DEFAULT FALSE,
`timestamp` TIMESTAMP NOT NULL DEFAULT NOW(),
`username` VARCHAR(255) NOT NULL,
`type` VARCHAR(255) NOT NULL
);
答案 0 :(得分:3)
在sa_signatures (type, order_id)
上创建索引。
除非LEFT JOIN
允许sa_signatures
中的空值,否则无需将查询转换为order_id
。使用索引,NOT IN
也会执行。但是,万一你好奇:
SELECT o.*
FROM sa_order o
LEFT JOIN
sa_signatures s
ON s.order_id = o.order_id
AND s.type = 'administrative director'
WHERE s.type IS NULL
您应该从NOT NULL
选择一个sa_signatures
列,以使WHERE
子句表现良好。
答案 1 :(得分:1)
您可以使用EXISTS替换[NOT] IN运算符以提高性能。
所以你会:
SELECT * FROM SA_ORDER WHERE NOT EXISTS
(SELECT ORDER_ID FROM SA_SIGNATURES
WHERE TYPE = 'administrative director'
AND ORDER_ID = SA_ORDER.ORDER_ID);
原因:“当使用”NOT IN“时,查询执行嵌套的全表扫描,而对于”NOT EXISTS“,查询可以使用子查询中的索引。”
答案 2 :(得分:0)
以下查询应该有效,但我怀疑您的真正问题是您没有适当的索引。您应该在ORDER_ID列的SA_SGINATURES表上有一个索引。
SELECT *
FROM
SA_ORDER
LEFT JOIN
SA_SIGNATURES
ON
SA_ORDER.ORDER_ID = SA_SIGNATURES.ORDER_ID AND
TYPE = 'administrative director'
WHERE
SA_SIGNATURES.ORDER_ID IS NULL;
答案 3 :(得分:0)
从sa_order中选择*作为内部联接sa_signature为o.orderid = sa.orderid上的s和sa.type ='administrative director'
另外,您可以在sa_signature表
中的类型上创建非聚集索引甚至更好 - 拥有一个包含typeid和typename的类型的主表,然后将类型保存为整数,而不是将类型保存为sa_signature表中的文本。那是因为在整数上计算比在文本上计算更快