Case:被驱动表没有使用索引导致性能差
发表于:2025-01-30 作者:千家信息网编辑
千家信息网最后更新 2025年01月30日,问题开发有一条insert SQL 是定时任务,内容如下, 每天需要约执行5-10次,笔者从select部分开始跑了一会没有结果,就放弃了,效率很差.INSERT INTO bs_sf_yd_flow
千家信息网最后更新 2025年01月30日Case:被驱动表没有使用索引导致性能差
问题
开发有一条insert SQL 是定时任务,内容如下, 每天需要约执行5-10次,笔者从select部分开始跑了一会没有结果,就放弃了,效率很差.
INSERT INTO bs_sf_yd_flow_check ( `merchantNo`, `sfBusinessId`, `sfMerOrderId`, `sfTradeTime`, `sfTradeAmount`, `sfDebitAmount`, `sfCreditAmount`, `sfBalance`, `sfAccNo`, `ydBusinessId`, `ydMerOrderId`, `ydTradeTime`, `ydTradeAmount`, `ydDebitAmount`, `ydCreditAmount`, `ydBalance`, `ydAccNo`, `tradeType`, `status`, `checkStatus`, `account_date`, `checkTime`, `createTime`, `updateTime`, `sfTradeType`)SELECT sf.merchantNo, sf.businessId, sf.merOrderId,sf.completeTime, sf.tradeAmount, sf.debitAmount, sf.creditAmount, sf.balance, sf.accNo, mr.businessId, mr.localOrderId, mr.tradeTime, CASE WHEN mr.fromUserId = '116' THEN mr.amount * - 1 ELSE mr.amount END AS ydTradeAmount, CASE WHEN mr.fromUserId = '116' THEN mr.amount WHEN mr.toUserId = '116' THEN 0 END AS ydDebitAmount, CASE WHEN mr.fromUserId = '116' THEN 0 WHEN mr.toUserId = '116' THEN mr.amount END AS ydCreditAmount, mr.accountBalance, IFNULL( CASE WHEN mr.fromUserId = '116' THEN mr.fromUserId WHEN mr.toUserId = '116' THEN mr.toUserId END, '' ) AS ydAccNo, mr.tradeType, 0, CASE WHEN ABS(sf.tradeAmount) = mr.amount THEN 3 WHEN mr.amount IS NULL THEN 6 ELSE 5 END AS checkStatus, sf.tradeTime, NOW(), NOW(), NOW(), sf.tradeTypeFROM bs_sf_flow sf LEFT JOIN money_record mr ON mr.bussflowno = sf.merOrderId AND sf.tradeTime = DATE_FORMAT(mr.tradeTime, '%Y-%m-%d') AND mr.ischeck = 1 AND ( mr.fromUserId = '116' OR mr.toUserId = '116' )WHERE sf.tradeTime = '20161212' AND sf.accNo = '00620000000010269449'
两个表的表结构如下
SF:CREATE TABLE `bs_sf_flow` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `businessId` varchar(40) NOT NULL COMMENT '账户流水号', `merchantNo` varchar(40) NOT NULL COMMENT '商户号', `merOrderId` varchar(40) NOT NULL COMMENT '商户订单号', `completeTime` datetime DEFAULT NULL COMMENT '订单完成时间', `tradeAmount` decimal(14,2) DEFAULT NULL COMMENT '交易金额', `debitAmount` decimal(14,2) DEFAULT NULL COMMENT '借方发生额', `creditAmount` decimal(14,2) DEFAULT NULL COMMENT '贷方发生额', `balance` decimal(14,2) DEFAULT NULL COMMENT '虚拟账户余额', `accNo` varchar(40) NOT NULL COMMENT '虚拟账户账号', `tradeType` varchar(40) NOT NULL COMMENT '业务类型', `status` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '状态0:初始', `createTime` datetime NOT NULL COMMENT '创建时间', `updateTime` datetime DEFAULT NULL COMMENT '更新时间', `merPlatAcctAlias` varchar(32) DEFAULT NULL COMMENT '商户平台收款账户别名,平台开立的账户账号别名,当商户开立多个账户时,必输', `merPlatAcctNo` varchar(80) DEFAULT NULL COMMENT '平台账户别名对应的账号', `tradeTime` date NOT NULL COMMENT '账务日期', PRIMARY KEY (`id`), KEY `idx_merOrderId` (`merOrderId`), KEY `idx_tradeTime` (`tradeTime`,`accNo`)) ENGINE=InnoDB AUTO_INCREMENT=1502748 DEFAULT CHARSET=utf8 COMMENT='三方流水表';MR:CREATE TABLE `money_record` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `toUserId` int(10) unsigned DEFAULT NULL COMMENT '资金汇入者的userid', `toUserNickname` varchar(100) DEFAULT NULL COMMENT '资金汇入者的昵称', `fromUserId` int(10) unsigned DEFAULT NULL COMMENT '资金汇出者的userid', `fromUserNickname` varchar(100) DEFAULT NULL COMMENT '资金汇出者的昵称', `amount` decimal(14,2) NOT NULL COMMENT '交易金额金额', `accountBalance` decimal(14,2) NOT NULL COMMENT '此交易完成后的账户余额', `businessId` varchar(50) NOT NULL DEFAULT '' COMMENT '关联的业务id,如充值订单号,提现批次号等', `tradeType` smallint(5) unsigned NOT NULL COMMENT '资金来往类型,小于1000的都是汇入,即资金增加;大于1000的都是汇出,即资金减少。详情见CommonDef中TRADE_TYPE_*', `tradeTime` datetime NOT NULL COMMENT '交易发生时间', `tradeChannel` smallint(5) unsigned DEFAULT NULL COMMENT '交易渠道', `tradeComment` varchar(300) DEFAULT NULL COMMENT '交易备注', `loanId` int(10) unsigned DEFAULT NULL COMMENT '关联的loanId', `loanTitle` varchar(64) DEFAULT NULL COMMENT '标名称', `loanPortraitPath` varchar(64) DEFAULT NULL COMMENT '标头像图片的路径', `bussflowno` varchar(128) DEFAULT NULL COMMENT '三方订单号', `localOrderId` varchar(128) DEFAULT NULL COMMENT '本地业务id', `ischeck` smallint(2) DEFAULT '1' COMMENT '是否与三方对账,0不对,1对', `fromAccBalance` decimal(14,2) DEFAULT NULL COMMENT '转出账户交易后余额', `toAccBalance` decimal(14,2) DEFAULT NULL COMMENT '转入账户处理后余额', `batchNo` varchar(32) DEFAULT NULL COMMENT '交易批次号', `originUserId` int(10) DEFAULT '0' COMMENT '交易来源用户', `updateTime` datetime DEFAULT NULL COMMENT '更新时间', `projectId` varchar(32) DEFAULT NULL COMMENT '项目ID', `tradePlatformType` smallint(5) unsigned DEFAULT '0' COMMENT '流水平台类型0:三方;10:托管;20:三方至托管;30:托管至三方;', PRIMARY KEY (`id`), KEY `fk_money_record_toUserId` (`toUserId`), KEY `idx_money_record_fromUserId` (`fromUserId`), KEY `idx_money_record_tradeTime` (`tradeTime`), KEY `idx_money_record_businessId` (`businessId`), KEY `idx_tradeType` (`tradeType`,`loanId`), KEY `idx_updateTime` (`updateTime`,`amount`)) ENGINE=InnoDB AUTO_INCREMENT=7166457 DEFAULT CHARSET=utf8
分析处理
单独看select部分的执行计划如下,可以发现被驱动表mr使用的是mr.fromUserId和mr.toUserId列上的索引,但是这两个索引作为删选条件并不好,rows有150多万行;
最好的情况是使用连接条件on mr.bussflowno = sf.merOrderId中mr.bussflowno列的索引,所以建议在mr.bussflowno上创建一个普通索引。
创建索引之后的执行计划如下,rows变为1,type从index_merge变成等值查询reg,只需0.2s便跑出select结果。
总结
被驱动表的连接条件on后面一定要有索引;
驱动表where后面的列最后要有筛选条件比较好的索引;
账户
交易
索引
资金
三方
时间
余额
商户
平台
条件
订单
驱动
业务
别名
类型
订单号
账号
金额
托管
两个
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
正在恢复数据库
软件开发有哪些晋升职位
网络安全消息写作
暴雪服务器怎么开
欧盟 网络安全
忻州网站建设软件开发
网络安全保卫支队内设机构
互联网科技的高端图片
优化网络安全策略目的
悍铭云服务器怎么打开
复学复课网络安全稳定运行
温州翻译软件开发
云流量自己做服务器
网络安全的威胁的过程
成都net软件开发哪家便宜
国家网络安全宣传日ppt
软件开发全栈是什么意思
服务器运算量
局域网访问电脑数据库
cbct网络安全要求
商拉拉平台东华软件开发
网络安全的手抄报字该怎么写
沈阳软件开发app公司有哪些
数据库索引建立 查找语句
宜兴一站式软件开发活动简介
优化网络安全策略目的
车企做软件开发工资
软件开发需要买mac吗
sql服务器名
无线网络安全设置查询