2010-04-07 99 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';