为什么MySQL Query会挂起?

时间:2010-04-07 09:25:36

标签: mysql

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个字段)记录。我不知道它是否会最终返回,因为我在实时服务器上运行并担心超载。

我正在成功地进行类似的查询和更复杂的查询。

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');

立即执行

3 个答案:

答案 0 :(得分:1)

因为有人锁定了其中一个表或一行。例如,如果您在会话中禁用了自动提交(因此可以回滚修改)并忘记提交,那么就会发生这种情况。

This document可能会有所帮助。

[编辑]发布表定义后,您可以看到两个连接列的类型不同。现在的问题是:运行查询时,哪种类型将上/下?在您的情况下,将PAYMENT_TRANSACTION_LOG_ID的类型转换为varchar可能会更好,尤其是如果您在TRANSACTION_ID上有一个索引(您应该为此查询创建索引)。

这样,将选择表tbl_order_head中的几行(甚至单个行),然后在表tbl_orders_log中进行快速查找。如果没有这个,数据库将从日志表中加载所有记录,并在找到的订单标题中检查每条记录是否匹配(加上将每个ID转换为标题中的类型等)。

答案 1 :(得分: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'

您的联接可能会导致数百/数十亿行被检查。您的表是否为此连接正确编入索引?

答案 2 :(得分: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';