左连接需要很长时间才能完成150 000行

时间:2017-02-19 00:53:22

标签: mysql

我在完成任务时遇到了一些困难。

以下是orders表中的一些数据:

+----+---------+
| id | bill_id |
+----+---------+
|  3 |       1 |
|  9 |       3 |
| 10 |       4 |
| 15 |       6 |
+----+---------+

以下是bills表中的一些数据:

+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
+----+

我想列出与bills无关联的所有order

为了达到这个目的,我认为LEFT JOIN的使用被占用了,所以我写了这个请求:

SELECT * FROM bills
  LEFT JOIN orders
    ON bills.id = orders.bill_id
WHERE orders.bill_id IS NULL;

我认为我会得到以下结果:

+----------+-----------+----------------+
| bills.id | orders.id | orders.bill_id |
+----------+-----------+----------------+
|        2 | NULL      | NULL           |
|        5 | NULL      | NULL           |
+----------+-----------+----------------+

但是我无法达到请求的结尾,它已经运行超过5分钟而没有结果,我停止了请求,因为这无论如何都不是生产时间。

我的真实数据集有超过150 000 orders和100 000 bills。数据集太大了吗?

我的请求在某处错了吗?

非常感谢你的提示!

编辑:旁注,表中没有定义外键... *飞走*

2 个答案:

答案 0 :(得分:2)

您的查询没问题。我会在写它时使用表别名:

SELECT b.*
FROM bills b LEFT JOIN
     orders o
     ON b.id = o.bill_id
WHERE o.bill_id IS NULL;

您可能不需要NULL中的orders列。

您需要orders(bill_id)上的索引:

create index idx_orders_billid on orders(bill_id);

答案 1 :(得分:0)

根据您的where声明,我假设您正在寻找没有账单的订单。

如果是这样的话,你不需要加入账单表,因为根据定义它们不存在。

你会找到

SELECT * FROM orders
WHERE orders.bill_id IS NULL;

性能更好的查询。

编辑:

抱歉,我错过了你的#34;我想列出所有与订单无关的账单。"在阅读问题时。正如@gordon所指出的,索引肯定会有所帮助。但是,如果更改方案是可行的,我宁愿有一个可以为空的bill.order_id列而不是order.bill_id因为你不需要左连接,内连接就足以获得订单账单,因为它会更快查询您的其他假设要求。