我在MySQL
配置中打开了慢速查询监控器。
以下是查询和时间:
时间:160330 20:54:11 User @ Host:user [user] @ [xx.xx.xxx.xxx] Query_time:8.794170 Lock_time:0.000141 Rows_sent:3942 Rows_examined:4742825 SET时间戳= 1459371251;
SELECT (SELECT (CASE WHEN ce_type = 'IN' then SUM(payment_amount)
END) as debit
FROM customer_payment_options cpo
WHERE wallet_id=cw.id
AND (cpo.real_account_type='HQ')
AND cpo.source_country_id='40'
GROUP BY cpo.wallet_id)
as debit,
(SELECT SUM(payment_amount)
as credit
FROM customer_payment_options cpo
WHERE wallet_id=cw.id
AND (cpo.real_account_type='HQ')
AND cpo.tran_id IS NOT NULL
AND cpo.source_country_id='40'
GROUP BY cpo.wallet_id)
as credit
FROM customer_wallet cw
WHERE cw.company_id='1'
AND cw.currency='40'
AND cw.is_approved = '1'
AND DATE(cw.date_added) < '2016-03-30';
customer_payment_options
上的索引:
company_id
tran_id
ce_id
wallet_id
我应该怎样做才能提高它的表现?
EXPLAIN :
http://i.stack.imgur.com/iH8rt.png
SCHEMA
CREATE TABLE `customer_payment_options` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`company_id` int(11) NOT NULL,
`local_branch_id` int(11) NOT NULL,
`tran_id` bigint(11) DEFAULT NULL,
`ce_id` int(11) DEFAULT NULL,
`wallet_id` int(11) DEFAULT NULL,
`reward_credit_id` int(11) DEFAULT NULL,
`ce_invoice_id` varchar(32) DEFAULT NULL,
`ce_type` enum('IN','OUT') DEFAULT NULL,
`payment_type` enum('CASH','DEBIT','CREDIT','CHEQUE','DRAFT','BANK_DEPOSIT','EWIRE','WALLET','LOAN','REWARD_CREDIT') NOT NULL,
`payment_amount` varchar(20) NOT NULL,
`payment_type_number` varchar(100) DEFAULT NULL,
`source_country_id` int(11) NOT NULL,
`real_account_id` int(11) DEFAULT NULL,
`real_account_type` enum('LOCAL','HQ') DEFAULT NULL,
`date_added` datetime NOT NULL,
`event_type` enum('MONEY_TRANSFER','CURRENCY_EXCHANGE','WALLET') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `company_id` (`company_id`),
KEY `real_account_type` (`real_account_type`),
KEY `tran_id` (`tran_id`),
KEY `ce_id` (`ce_id`),
KEY `wallet_id` (`wallet_id`),
CONSTRAINT `customer_payment_options_ibfk_4` FOREIGN KEY (`wallet_id`) REFERENCES `customer_wallet` (`id`),
CONSTRAINT `customer_payment_options_ibfk_1` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`),
CONSTRAINT `customer_payment_options_ibfk_2` FOREIGN KEY (`tran_id`) REFERENCES `transaction` (`id`),
CONSTRAINT `customer_payment_options_ibfk_3` FOREIGN KEY (`ce_id`) REFERENCES `currency_exchange` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=412 DEFAULT CHARSET=utf8
CREATE TABLE `customer_wallet` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`wallet_unique_id` varchar(100) DEFAULT NULL,
`company_id` int(11) NOT NULL,
`branch_admin_id` int(11) DEFAULT NULL,
`emp_id` int(11) DEFAULT NULL,
`emp_type` enum('SUPER_ADMIN','ADMIN','AGENT_ADMIN','AGENT','OVER_AGENT_ADMIN','OVER_AGENT') DEFAULT NULL,
`cus_id` bigint(11) NOT NULL,
`tran_id` bigint(11) DEFAULT NULL,
`beehive_id` int(11) DEFAULT NULL,
`type` enum('DEPOSIT','WITHDRAW','TRANSACTION') NOT NULL,
`sub_type` enum('MONEY_TRANSFER','BEEHIVE_DEPOSIT') DEFAULT NULL,
`credit_in` varchar(20) DEFAULT NULL,
`credit_out` varchar(20) DEFAULT NULL,
`currency` varchar(20) NOT NULL,
`date_added` datetime NOT NULL,
`note` varchar(255) DEFAULT NULL,
`location` enum('DIRECT') DEFAULT NULL,
`is_approved` enum('0','1') NOT NULL DEFAULT '1',
`idebit_issconf` varchar(50) DEFAULT NULL,
`idebit_issname` varchar(50) DEFAULT NULL,
`idebit_isstrack2` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `cus_id` (`cus_id`),
KEY `company_id` (`company_id`),
KEY `branch_admin_id` (`branch_admin_id`),
KEY `emp_id` (`emp_id`),
KEY `tran_id` (`tran_id`),
KEY `beehive_id` (`beehive_id`),
CONSTRAINT `customer_wallet_ibfk_1` FOREIGN KEY (`cus_id`) REFERENCES `customers` (`id`),
CONSTRAINT `customer_wallet_ibfk_2` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`),
CONSTRAINT `customer_wallet_ibfk_3` FOREIGN KEY (`tran_id`) REFERENCES `transaction` (`id`),
CONSTRAINT `customer_wallet_ibfk_4` FOREIGN KEY (`emp_id`) REFERENCES `employees` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=152 DEFAULT CHARSET=utf8
答案 0 :(得分:3)
您正在做什么作为每个钱包ID的相关查询,以获得相应的借记和信用。看来你的每个钱包ID都有一条记录。这很忙。根据您的标准(包括每个钱包ID的加入)加入客户付款表。然后,将CASE简化为SUM(case / when)作为相应的借方/贷方。
我不知道你的表格列的基本标准,但我甚至会对(而且确实)包括不包括CE_TYPE ='IN',因为这看起来是借记的基础,你不会错误地算作一部分也是一种信用。再次,不知道字段,trans_id,类型的相关性。
现在,如上所述,在单个字段上使用单个索引无助于优化此查询。我会建议以下索引。
表索引 customer_wallet(company_id,is_approved,currency,id,date_added) customer_payment_options(wallet_id,account_type,country_id)
SELECT
cw.wallet_id,
SUM( case when cpo.ce_type = 'IN'
then cpo.payment_amount
ELSE 0 end ) as Debit,
SUM( case when NOT cpo.ce_type = 'IN'
AND cpo.tran_id IS NOT NULL
then cpo.payment_amount
ELSE 0 end ) as Credit
FROM
customer_wallet cw
JOIN customer_payment_options cpo
ON cw.id = cpo.wallet_id
AND cpo.real_account_type = 'HQ'
AND cpo.source_country_id = '40'
WHERE
cw.company_id = '1'
AND cw.currency = '40'
AND cw.is_approved = '1'
AND cw.date_added < '2016-03-30'
GROUP BY
cw.id
另外一条评论。如果您的ID列,货币标记,国家/地区ID,已批准实际上是表结构中的数值,请删除引号并直接比较数值。另外,对于你的date_added。你有基于DATE(date_added)的那个。对列执行功能无法充分利用索引。由于date()剥离了日期/时间戳列的任何时间部分,并且您要求所有添加的数量少于3月30日,因此3月29日晚上11:59:59的添加日期仍然低于3月30日12:凌晨00:00,所以不需要转换日期。
正如Ivan(下文)所评论的,如果您想要所有电子钱包ID,无论是否有任何付款(借记或贷记),请从联接更改为LEFT JOIN。
答案 1 :(得分:0)
您需要添加索引和多列索引以使其快速。 请记住,如果你有大表,额外的索引将减慢插入速度,因为索引文件更新将花费更多的时间。
如果col1和col2上存在多列索引,则相应 行可以直接获取。如果存在单独的单列索引 在col1和col2上,优化器尝试使用索引合并 优化(参见第8.2.1.4节“索引合并优化”)或 试图通过决定哪个索引来找到最严格的索引 排除更多行并使用该索引来获取行。
如果表有多列索引,则表示最左边的前缀 优化器可以使用index来查找行。例如,如果 你有一个三列索引(col1,col2,col3),你已编入索引 搜索(col1),(col1,col2)和(col1,col2,col3)的功能。