簡體   English   中英

為什么我的查詢這么慢? 試圖在mysql中找到左邊的空字段

[英]Why is my query so slow? Trying to find the null fields on a left join in mysql

編輯:更新了以下Bill Karwin的建議。 還是很慢。

我正在嘗試編寫一個查詢,該查詢將查找訂單上的所有項目,這些項目輸入到倉庫中,該倉庫中沒有該項目的記錄。 例如,如果為倉庫A輸入了項目XYZ,但倉庫A實際上沒有攜帶項目XYZ,我希望訂單項目顯示在我的報告中。

我能夠很好地運行查詢,但似乎需要永遠(50秒)。 它似乎主要掛在where子句中的“is null”條件。 如果我使用“is null”刪除條件並運行它,它將在大約4.8秒內執行。 這是我的查詢:

SELECT
saw_order.Wo,
saw_orderitem.Item,
saw_orderitem.Stock,
saw_order.`Status`,
saw_order.`Date`,
saw_orderitem.Warehouse,
saw_stockbalance.Balno,
saw_stockbalance.Stock
FROM
saw_order
Inner Join saw_orderitem ON saw_order.Wo = saw_orderitem.Wo
Inner Join saw_stock ON saw_orderitem.Stock = saw_stock.Stock
Left Join saw_stockbalance ON saw_orderitem.Stock = saw_stockbalance.Stock 
    AND saw_orderitem.Warehouse = saw_stockbalance.Warehouse
WHERE
saw_order.`Status` Between 3 and 81 and
saw_stockbalance.Stock Is Null

當我explain上面的查詢時,我看到:

+----+-------------+------------------+--------+------------------------------+---------+---------+-------------------------------------------------------+-------+-------------------------+
| id | select_type | table            | type   | possible_keys                | key     | key_len | ref                                                   | rows  | Extra                   |
+----+-------------+------------------+--------+------------------------------+---------+---------+-------------------------------------------------------+-------+-------------------------+
|  1 | SIMPLE      | saw_stock        | index  | PRIMARY                      | PRIMARY | 17      | NULL                                                  | 32793 | Using index             |
|  1 | SIMPLE      | saw_orderitem    | ref    | PRIMARY,Stock,StockWarehouse | Stock   | 17      | saws.saw_stock.Stock                                  |    68 |                         |
|  1 | SIMPLE      | saw_order        | eq_ref | PRIMARY,Status               | PRIMARY | 4       | saws.saw_orderitem.Wo                                 |     1 | Using where             |
|  1 | SIMPLE      | saw_stockbalance | ref    | Stock,Warehouse              | Stock   | 20      | saws.saw_orderitem.Stock,saws.saw_orderitem.Warehouse |     1 | Using where; Not exists |
+----+-------------+------------------+--------+------------------------------+---------+---------+-------------------------------------------------------+-------+-------------------------+

我很確定我的聯接中各個表的所有字段都有索引,但無法弄清楚如何重寫查詢以使其更快。

編輯:這是我在我的表上設置的索引:

mysql> show index from saw_order;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| saw_order |          0 | PRIMARY  |            1 | Wo          | A         |      553425 | NULL     | NULL   |      | BTREE      |         |
| saw_order |          1 | Customer |            1 | Customer    | A         |       14957 | NULL     | NULL   |      | BTREE      |         |
| saw_order |          1 | Other    |            1 | Other       | A         |         218 | NULL     | NULL   |      | BTREE      |         |
| saw_order |          1 | Site     |            1 | Site        | A         |           8 | NULL     | NULL   |      | BTREE      |         |
| saw_order |          1 | Date     |            1 | Date        | A         |        1594 | NULL     | NULL   |      | BTREE      |         |
| saw_order |          1 | Status   |            1 | Status      | A         |          15 | NULL     | NULL   |      | BTREE      |         |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
6 rows in set

mysql> show index from saw_orderitem;
+---------------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table         | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| saw_orderitem |          0 | PRIMARY        |            1 | Wo          | A         | NULL        | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          0 | PRIMARY        |            2 | Item        | A         |     1842359 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | Stock          |            1 | Stock       | A         |       27093 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | Product        |            1 | Product     | A         |         803 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | GGroup         |            1 | GGroup      | A         |         114 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | ShipVia        |            1 | ShipVia     | A         |         218 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | Warehouse      |            1 | Warehouse   | A         |           9 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | StockWarehouse |            1 | Stock       | A         |       27093 | NULL     | NULL   |      | BTREE      |         |
| saw_orderitem |          1 | StockWarehouse |            2 | Warehouse   | A         |       49793 | NULL     | NULL   |      | BTREE      |         |
+---------------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
9 rows in set

mysql> show index from saw_stock;
+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table     | Non_unique | Key_name          | Seq_in_index | Column_name       | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| saw_stock |          0 | PRIMARY           |            1 | Stock             | A         |       32793 | NULL     | NULL   |      | BTREE      |         |
| saw_stock |          1 | Class             |            1 | Class             | A         |         655 | NULL     | NULL   | YES  | BTREE      |         |
| saw_stock |          1 | DateFirstReceived |            1 | DateFirstReceived | A         |        2732 | NULL     | NULL   |      | BTREE      |         |
+-----------+------------+-------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set

mysql> show index from saw_stockbalance;
+------------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table            | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| saw_stockbalance |          0 | PRIMARY   |            1 | Balno       | A         |      146315 | NULL     | NULL   |      | BTREE      |         |
| saw_stockbalance |          1 | Stock     |            1 | Stock       | A         |       36578 | NULL     | NULL   |      | BTREE      |         |
| saw_stockbalance |          1 | Stock     |            2 | Warehouse   | A         |      146315 | NULL     | NULL   |      | BTREE      |         |
| saw_stockbalance |          1 | Warehouse |            1 | Warehouse   | A         |          11 | NULL     | NULL   |      | BTREE      |         |
+------------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
4 rows in set

有任何想法嗎?

我試着讓它使用覆蓋索引 也就是說,不測試Balno是否為null,而是測試左外連接條件中的一列是否為空。 例如StockWarehouse

您還應該在兩個表saw_orderitemsaw_stockbalance的兩列( StockWarehouse )上定義索引。

嘗試:

SELECT t.wo,
       soi.item,
       soi.stock,
       t.Status,
       t.Date,
       soi.warehouse,
       NULL 'balno',  --ssb.Balno,
       NULL 'stock', --ssb.Stock
  FROM SAW_ORDER t
  JOIN SAW_ORDERITEM soi ON soi.wo = t.wo
  JOIN SAW_STOCK ss ON ss.stock = soi.stock
 WHERE t.status BETWEEN 3 AND 81 
   AND NOT EXISTS (SELECT NULL
                     FROM SAW_STOCKBALANCE ssb
                    WHERE ssb.stock != soi.stock
                      AND ssb.warehouse = soi.warehouse)

查詢的問題是您正在檢查LEFT JOIN上的空值...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM