2010-04-07 215 views
6
SELECT * 
FROM tbl_order_head AS o 
INNER JOIN tbl_orders_log AS c 
ON o.PAYMENT_TRANSACTION_LOG_ID=c.TRANSACTION_ID 
WHERE o.VISUAL_ID = '77783'; 

tbl_order_head 67,000(30字段)記錄,tbl_orders_log 17000(5字段)記錄。我不知道它是否會最終返回,因爲我在運行的服務器上運行它並擔心超載。爲什麼這個MySQL查詢掛起?

我正在做類似的查詢和更復雜的查詢成功。

tbl_orders_log

Field Type Comment 
ID bigint(20) NOT NULL 
TRANSACTION_ID varchar(1000) NULL 
CREATED datetime NULL 
AMENDED datetime NULL 
PAYMENT_CARD_NUMBER varchar(255) NULL 
PAYMENT_CARD_TYPE varchar(255) NULL 
SESSION_ID varchar(255) NULL 
TRANSACTION_TYPE varchar(255) NULL 
TRANSACTION_VALUE varchar(255) NULL 
LOG_DATA text NULL 

索引信息

Indexes Columns Index_Type 
PRIMARY ID Unique 

tbl_order_head

CREATE TABLE `tbl_order_head` (
    `ID` varchar(255) NOT NULL, 
    `VISUAL_ID` decimal(20,0) DEFAULT NULL, 
    `CREATED` datetime DEFAULT NULL, 
    `AMENDED` datetime DEFAULT NULL, 
    `CUSTOMER_ID` varchar(255) DEFAULT NULL, 
    `BILLING_ID` varchar(255) DEFAULT NULL, 
    `ORDER_LINES_ITEM_VALUE` varchar(20) DEFAULT NULL, 
    `DELIVERY_VALUE` varchar(20) DEFAULT NULL, 
    `ORDER_LINES_ITEM_TAX` varchar(20) DEFAULT NULL, 
    `DELIVERY_TAX` varchar(20) DEFAULT NULL, 
    `DELIVERY_ALLOCATED_ITEMS_VALUE` varchar(20) DEFAULT NULL, 
    `DELIVERY_ALLOCATED_ITEMS_TAX` varchar(20) DEFAULT NULL, 
    `DELIVERY_ALLOCATED_ITEMS_TAX_DEDUCTION` varchar(20) DEFAULT NULL, 
    `DELIVERY_TAX_DEDUCTION` varchar(20) DEFAULT NULL, 
    `LOYALTY_CARD_POINTS_EARNED` varchar(10) DEFAULT NULL, 
    `LOYALTY_CARD_POINTS_REDEEMED` varchar(10) DEFAULT NULL, 
    `LOYALTY_CARD_POINTS_REDEEMED_VALUE` varchar(20) DEFAULT NULL, 
    `VOUCHER_CODE` varchar(50) DEFAULT NULL, 
    `AFFILIATE_CODE` varchar(50) DEFAULT NULL, 
    `LOYALTY_CARD_NUMBER` varchar(209) DEFAULT NULL, 
    `REDEEM_LOYALTY_CARD_POINTS` varchar(1) DEFAULT NULL, 
    `SOURCE` varchar(50) DEFAULT NULL, 
    `SKU_DATA` text, 
    `SKU_TAX_DATA` text, 
    `DISCOUNT_DATA` text, 
    `PAYMENT_CARD_TYPE` varchar(6) DEFAULT NULL, 
    `PAYMENT_CARD_NUMBER` varchar(255) DEFAULT NULL, 
    `PAYMENT_CARD_START_MONTH` varchar(6) DEFAULT NULL, 
    `PAYMENT_CARD_EXPIRY_MONTH` varchar(6) DEFAULT NULL, 
    `PAYMENT_CARD_START_YEAR` varchar(6) DEFAULT NULL, 
    `PAYMENT_CARD_EXPIRY_YEAR` varchar(6) DEFAULT NULL, 
    `PAYMENT_CARD_ISSUE_NUMBER` varchar(3) DEFAULT NULL, 
    `PAYMENT_CARD_SECURITY_NUMBER` varchar(4) DEFAULT NULL, 
    `PAYMENT_CARD_NAME` varchar(50) DEFAULT NULL, 
    `PAYMENT_CARD_SAVE` varchar(1) DEFAULT NULL, 
    `PAYMENT_CARD_CHARGE_AMOUNT` varchar(10) DEFAULT NULL, 
    `SAVED_PAYMENT_CARD_ID` varchar(255) DEFAULT NULL, 
    `SAVED_PAYMENT_CARD_SECURITY_NUMBER` varchar(255) DEFAULT NULL, 
    `GIFT_VOUCHER_DATA` text, 
    `GIFT_VOUCHER_APPLIED_VALUE` varchar(10) DEFAULT NULL, 
    `LOYALTY_EARNED_SKU_DATA` text, 
    `LOYALTY_REDEMPTION_SKU_DATA` text, 
    `LOYALTY_REDEMPTION_DEDUCTED_SKU_DATA` text, 
    `PAYMENT_CARD_AUTH_CODE` varchar(10) DEFAULT NULL, 
    `PAYMENT_TRANSACTION_LOG_ID` text, 
    `CREATED_BY` varchar(20) DEFAULT NULL, 
    `BASKET_ID` varchar(255) DEFAULT NULL, 
    `SKU_DESCRIPTION_XREF` text, 
    `IP_TRANSACTION_NUMBER` varchar(255) DEFAULT NULL, 
    `MEMS_BESPOKE_DISCOUNT_DATA` text, 
    `IP_EXPORTED` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `CUSTOMER_ID` (`CUSTOMER_ID`,`CREATED`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

您好我有(有幫助) 改寫查詢

SELECT * FROM tbl_orders_log WHERE TRANSACTION_ID=(SELECT o.PAYMENT_TRANSACTION_LOG_ID FROM tbl_order_head AS o WHERE o.VISUAL_ID = '77783'); 

立即執行

+0

如果其中一個表被鎖定,你檢查了你的數據庫嗎? – hallie 2010-04-07 09:27:43

回答

1

因爲有人鎖定了其中一個表或單個行。例如,如果您在會話中禁用了自動提交(因此您可以回滾您的修改)並忘記在此提交,就可能發生這種情況。

This document可能有幫助。

[編輯]發佈表定義後,您可以看到兩個連接列的類型不同。現在的問題是:當你運行查詢時,哪種類型會被上/下轉換?在你的情況下,最好將PAYMENT_TRANSACTION_LOG_ID的類型轉換爲varchar,尤其是如果你有一個TRANSACTION_ID(你應該爲這個查詢創建)索引。

這樣,將從表tbl_order_head中選擇幾行(甚至單個),然後在表tbl_orders_log中進行快速查找。如果沒有這個,數據庫將加載日誌表中的所有記錄,並檢查每個記錄中找到的訂單頭中的匹配項(並將每個ID轉換爲頭中的類型等)。

+0

嗯從來沒有考慮過這一點,但我正在運行服務器上的控制檯查詢。我猜個人記錄可能會被鎖定,但我怎麼知道?無論如何我可以查看單個表格? – zzapper 2010-04-07 09:39:34

+0

查看確定鎖定和死鎖的鏈接。 – 2010-04-07 12:46:58

+0

爲TRANSACTION_ID創建索引並立即運行查詢。所以這解決了我的問題,謝謝 – zzapper 2010-04-08 10:04:57

1

您是否在查詢上運行了EXPLAIN以查看查詢計劃?

EXPLAIN SELECT * FROM tbl_order_head AS o INNER JOIN tbl_orders_log AS 
c ON o.PAYMENT_TRANSACTION_LOG_ID=c.TRANSACTION_ID WHERE o.VISUAL_ID = '77783' 

您的連接可能會導致數百萬/數十億行正在檢查。您的表格是否正確編入了此連接的索引?

+0

解釋返回 「id」,「select_type」,「table」,「type」,「possible_keys」,「key」,「key_len」,「ref」,「rows」, 「Extra」 「1」,「SIMPLE」,「c」,「ALL」,\ N,\ N,\ N,\ N,「16633」,「」 「1」「SIMPLE」 o「,」ALL「,\ N,\ N,\ N,\ N,」59696「,」使用where「 – zzapper 2010-04-07 09:41:48

+0

看起來它正在執行表掃描(檢查所有行),如果你可以'SHOW CREATE表

\ G'用於這個查詢中的兩個表,並將它包含在你的問題中。 – 2010-04-07 10:04:56

+0

我現在可以看到索引的transaction_id是一個varchar(1000),另一個奇怪的是一個文本字段(數據庫不是我設計的) – zzapper 2010-04-07 10:36:25

0

我認爲它應該是o.TRANSACTION_ID和c.PAYMENT_TRANSACTION_LOG_ID而不是c.TRANSACTION_ID和o.PAYMENT_TRANSACTION_LOG_ID。然後查詢應該看起來像這樣:

SELECT * FROM tbl_order_head o 
INNER JOIN tbl_orders_log c 
ON c.PAYMENT_TRANSACTION_LOG_ID=o.TRANSACTION_ID 
WHERE o.VISUAL_ID = '77783';