MySQL连接性能问题或条件

MySQL连接性能问题或条件,mysql,Mysql,有谁能想出一种更有效的方法来编写这个查询,因为我运行它时它总是超时 SELECT orders.OrderKey, shipout.primary_subcategory FROM orders INNER JOIN orderitems ON orderitems.OrderID = orders.OrderID INNER JOIN subjects ON subjects.SubjectID = orderitems.SubjectID INNER JOIN su

有谁能想出一种更有效的方法来编写这个查询,因为我运行它时它总是超时

SELECT 
orders.OrderKey,
shipout.primary_subcategory
FROM
orders
    INNER JOIN
orderitems ON orderitems.OrderID = orders.OrderID
    INNER JOIN
subjects ON subjects.SubjectID = orderitems.SubjectID
    INNER JOIN
subjectdetails ON subjectdetails.SubjectID = subjects.SubjectID
    INNER JOIN
shipout ON shipout.id_invoice = subjects.SubjectKey
        OR shipout.id_invoice = orders.OrderKey
GROUP BY orders.orderkey
如果我删除或条件,它将在.2秒内完成。即使我用orders表而不是subjects表切换最后一个连接,它也会在.1秒内完成

shipout ON shipout.id_invoice = orders.OrderKey
GROUP BY orders.orderkey
但是当我试图同时加入两者时,或者它超时了。下面是解释:

+----+-------------+----------------+--------+-----------------------------------------+----------------------+---------+--------------------------+--------+----------------------------------------------------+
| id | select_type |     table      |  type  |              possible_keys              |         key          | key_len |           ref            |  rows  |                       Extra                        |
+----+-------------+----------------+--------+-----------------------------------------+----------------------+---------+--------------------------+--------+----------------------------------------------------+
|  1 | SIMPLE      | shipout        | ALL    |                                         |                      |         |                          |  10658 | Using temporary; Using filesort                    |
|  1 | SIMPLE      | subjectdetails | index  | PRIMARY                                 | SubjectDetails_ID    |     768 |                          | 455446 | Using index; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | subjects       | eq_ref | PRIMARY,Subjects_SubjectKey             | PRIMARY              |       4 | subjectdetails.SubjectID |      1 |                                                    |
|  1 | SIMPLE      | orderitems     | ref    | OrderItems_OrderID,OrderItems_SubjectID | OrderItems_SubjectID |       5 | subjectdetails.SubjectID |      1 |                                                    |
|  1 | SIMPLE      | orders         | eq_ref | PRIMARY,Orders_OrderKey                 | PRIMARY              |       4 | orderitems.OrderID       |      1 | Using where                                        |
+----+-------------+----------------+--------+-----------------------------------------+----------------------+---------+--------------------------+--------+----------------------------------------------------+

需要注意的一点是,我不是数据库管理员,所以我不能索引表。看起来subjectdetails是,但我不确定是否要发货。

您可以尝试重写最后一个连接,如下所示:

shipout ON shipout.id_invoice = COALESCE(subjects.SubjectKey, orders.OrderKey)

这样就消除了OR,但将连接相同的行。这仅在subjects.SubjectKey/orders.OrderKey为NULL时有效,如果另一个在创建联接时不为NULL,则很难在不知道确切数据结构的情况下进行判断。

您可以尝试像这样重写最后一个联接:

shipout ON shipout.id_invoice = COALESCE(subjects.SubjectKey, orders.OrderKey)

这样就消除了OR,但将连接相同的行。这仅在subjects.SubjectKey/orders.OrderKey为NULL时有效,如果另一个在进行连接时不为NULL,则很难在不知道确切数据结构的情况下进行判断。

当前查询的联合重写
还可以通过正确的索引获得性能

查询

SELECT 
orders.OrderKey,
shipout.primary_subcategory
FROM
orders
    INNER JOIN
orderitems ON orderitems.OrderID = orders.OrderID
    INNER JOIN
subjects ON subjects.SubjectID = orderitems.SubjectID
    INNER JOIN
subjectdetails ON subjectdetails.SubjectID = subjects.SubjectID
    INNER JOIN
shipout ON shipout.id_invoice = subjects.SubjectKey
GROUP BY orders.orderkey

UNION ALL

SELECT 
orders.OrderKey,
shipout.primary_subcategory
FROM
orders
    INNER JOIN
orderitems ON orderitems.OrderID = orders.OrderID
    INNER JOIN
subjects ON subjects.SubjectID = orderitems.SubjectID
    INNER JOIN
subjectdetails ON subjectdetails.SubjectID = subjects.SubjectID
    INNER JOIN
shipout ON shipout.id_invoice = orders.OrderKey
GROUP BY orders.orderkey

需要注意的一点是,我不是数据库管理员,因此无法编制索引 桌子


但仍向数据库管理员寻求建议和索引。对当前查询的联合重写
还可以通过正确的索引获得性能

查询

SELECT 
orders.OrderKey,
shipout.primary_subcategory
FROM
orders
    INNER JOIN
orderitems ON orderitems.OrderID = orders.OrderID
    INNER JOIN
subjects ON subjects.SubjectID = orderitems.SubjectID
    INNER JOIN
subjectdetails ON subjectdetails.SubjectID = subjects.SubjectID
    INNER JOIN
shipout ON shipout.id_invoice = subjects.SubjectKey
GROUP BY orders.orderkey

UNION ALL

SELECT 
orders.OrderKey,
shipout.primary_subcategory
FROM
orders
    INNER JOIN
orderitems ON orderitems.OrderID = orders.OrderID
    INNER JOIN
subjects ON subjects.SubjectID = orderitems.SubjectID
    INNER JOIN
subjectdetails ON subjectdetails.SubjectID = subjects.SubjectID
    INNER JOIN
shipout ON shipout.id_invoice = orders.OrderKey
GROUP BY orders.orderkey

需要注意的一点是,我不是数据库管理员,因此无法编制索引 桌子



但仍需向数据库管理员寻求建议和索引。

“需要注意的是,我不是数据库管理员,因此无法为表编制索引”向数据库管理员寻求建议和索引。。在解释中看到“使用临时;使用文件排序”和“使用索引;使用联接缓冲区(块嵌套循环)”是个坏消息,需要确定索引。。很可能将OR语句重写为UNION类型的查询也可以通过正确的索引提高性能。为什么需要subjectdetails?它似乎没有被使用?@ewramner你是对的,它不适用于此查询。在上一次查询中,我从该表中选择了一些列,但在删除所选列时忘记删除联接。但是,无论哪种方式,我在删除连接时都会遇到同样的问题“需要注意的是,我不是数据库管理员,所以我不能索引表”,请数据库管理员提供建议和索引。。在解释中看到“使用临时;使用文件排序”和“使用索引;使用联接缓冲区(块嵌套循环)”是个坏消息,需要确定索引。。很可能将OR语句重写为UNION类型的查询也可以通过正确的索引提高性能。为什么需要subjectdetails?它似乎没有被使用?@ewramner你是对的,它不适用于此查询。在上一次查询中,我从该表中选择了一些列,但在删除所选列时忘记删除联接。不管怎样,我都遇到了与join removedUsing COALESCE相同的问题,因为它阻止MySQL在subjects.SubjectKey或orders.OrderKeyGood上使用索引,但如果查询在毫秒内运行,而没有或这仍然可以解决问题。最近解决了一个非常类似的性能问题。我喜欢这个想法,并且可以看到它的应用,但是是的,它不适用于我的特定数据集使用COALESCE不是一个好主意,因为它阻止MySQL在subjects.SubjectKey或orders.OrderKeyGood point上使用索引,如果查询在毫秒内运行而没有或,这仍然可以解决问题。最近解决了一个非常类似的性能问题。我喜欢这个想法,并且可以看到它的应用,但是是的,它不适用于我的特定数据集。这是一个很好的建议。今后我必须记住工会的接线员。这非常有效,只需0.4秒即可查询。只有当您使用两个独立的(索引)列(如
,其中column1=1或column2=1
)时,此技巧才有意义,这些列可以重写为
UNION ALL
方法@Brandon
其中column1=1或column1=2
联合所有
中重新布线(其中column1=1或column1=2
将(1,2)
中的列重写到
中会更有意义。有意义。谢谢你的进一步解释。很好的建议。今后我必须记住工会的接线员。这非常有效,只需0.4秒即可查询。只有当您使用两个独立的(索引)列(如
,其中column1=1或column2=1
)时,此技巧才有意义,这些列可以重写为
UNION ALL
方法@Brandon
其中column1=1或column1=2
联合所有
中重新布线(其中column1=1或column1=2
将(1,2)
中的列重写到
中会更有意义。有意义。谢谢你的进一步解释。