我在一个有4.45百万行的表上查询运行,查询花了15-20分钟才完成操作。我也试过将引擎从Innodb更改为MyISAM,但没有任何工作。我还试图添加类型为normal且unique的多个索引,但它仍然需要相同的时间。
这是我的查询:
SELECT
a.source, a.destination, a.forward_to, a.start_epoch, a.end_epoch, a.duration, a.billsec, a.outbound_billsec, a.pool_id, a.group_id, a.cost, a.outbound_cost, a.net, a.keep, a.payin, a.payout, a.campaign_id, a.buyer, a.hangup_cause, a.endpoint_disposition, a.uuid, a.agreement, a.agreement_type, a.contract, a.contract_type, a.sip_received_ip,a.termination_ip,
REPLACE(REPLACE(ifnull(b.line_type,''),'\n',' '),'\r',' ') AS line_type,
REPLACE(REPLACE(ifnull(b.ocn,''),'\n',' '),'\r',' ') AS ocn,
REPLACE(REPLACE(ifnull(b.spid_carrier_name,''),'\n',' '),'\r',' ') AS spid_carrier_name
INTO OUTFILE '/tmp/test-husnain01'
FIELDS TERMINATED BY ',' FROM inbound_022018 a
LEFT JOIN wireless_checks b ON (a.uuid = b.uuid)
WHERE date(a.start_epoch)='2018-02-19' AND
a.endpoint_disposition='ANSWER' AND
a.direction='inbound' AND
a.billed=1;
以下是我的表格结构(inbound_022018):
CREATE TABLE `inbound_022018` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`destination` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`prefix` int(22) NOT NULL,
`forward_to` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`supplier` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`agreement` int(11) NOT NULL,
`agreement_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`payout` float(11,4) NOT NULL,
`pool_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`campaign_id` bigint(22) NOT NULL,
`lead` int(1) NOT NULL,
`cpl` float(11,4) NOT NULL,
`buyer` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`contract` int(11) NOT NULL,
`contract_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`payin` float(11,4) NOT NULL,
`gross` float(11,4) NOT NULL,
`cost` float(11,4) NOT NULL,
`outbound_cost` float(11,4) NOT NULL,
`net` float(11,4) NOT NULL,
`keep` float(11,4) NOT NULL,
`direction` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`session_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`sip_from_uri` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`sip_received_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`domain_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`sip_req_uri` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`endpoint_disposition` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`hangup_cause` varchar(80) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`hangup_cause_q850` varchar(80) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`start_epoch` datetime DEFAULT NULL,
`answer_epoch` datetime DEFAULT NULL,
`bridge_epoch` datetime DEFAULT NULL,
`progress_epoch` datetime DEFAULT NULL,
`progress_media_epoch` datetime NOT NULL,
`end_epoch` datetime NOT NULL,
`digits_dialed` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`last_app` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`last_arg` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`duration` int(11) NOT NULL,
`g30` int(1) DEFAULT NULL,
`billsec` int(11) NOT NULL,
`outbound_duration` int(11) NOT NULL,
`outbound_billsec` int(11) NOT NULL,
`progresssec` int(11) NOT NULL,
`answersec` int(11) NOT NULL,
`waitsec` int(11) NOT NULL,
`progress_mediasec` int(11) NOT NULL,
`flow_billsec` int(11) NOT NULL,
`sip_hangup_disposition` int(11) NOT NULL,
`callForwarded` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`forwardUuid` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`call_type` enum('s','v') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 's',
`billed` int(1) NOT NULL,
`uc` int(1) NOT NULL,
`suc` int(1) NOT NULL,
`callinfo` varchar(250) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`termination_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`switchname` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`org_charges` float(11,4) NOT NULL,
`call_summary` text,
PRIMARY KEY (`id`),
UNIQUE KEY `index_inbound_0717` (`id`) USING BTREE,
UNIQUE KEY `index_uuid` (`uuid`) USING BTREE,
UNIQUE KEY `index_all` (`id`,`campaign_id`,`session_id`,`uuid`) USING BTREE,
KEY `index_source` (`source`) USING BTREE,
KEY `index_destination` (`destination`) USING BTREE,
KEY `index_endpoint` (`endpoint_disposition`) USING BTREE,
KEY `index_build` (`billed`) USING BTREE,
KEY `index_campainid` (`campaign_id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=4457485 DEFAULT CHARSET=latin1
这是第二个表(wireless_checks):
CREATE TABLE `wireless_checks` (
`id` int(22) NOT NULL AUTO_INCREMENT,
`date` varchar(10) NOT NULL,
`uuid` varchar(100) NOT NULL,
`tn` varchar(11) NOT NULL,
`lrn` varchar(11) NOT NULL,
`ported_status` varchar(2) NOT NULL,
`ported_date` varchar(11) NOT NULL,
`ocn` varchar(10) NOT NULL,
`line_type` int(1) NOT NULL,
`spid` varchar(10) NOT NULL,
`spid_carrier_name` varchar(100) NOT NULL,
`spid_carrier_type` varchar(10) NOT NULL,
`altspid_carrier_name` varchar(10) NOT NULL,
`altspid_carrier_type` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_uuid` (`uuid`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=36175 DEFAULT CHARSET=latin1
请指导我如何优化此查询以减少执行时间。如果有任何其他方法可以完成,我也愿意解决方法。任何帮助将不胜感激。
由于
Husnain
答案 0 :(得分:0)
一个应该有所作为的提示是,而不是做
WHERE date(a.start_epoch)='2018-02-19'
您应该考虑事先计算,然后使用实际值,即1518998400
这是一个红旗的原因是,通过在比较的左侧放置一个函数,你强迫数据库进行全表扫描,在所有4.45m行上运行该函数,只是为了处理WHERE
条款。如果您将列本身与实际值进行比较而不使用DATE
函数,那么MySQL可以更有效地优化查询,并且如果有可用的话,将在a.start_epoch
上使用索引。
要创建该索引,只需执行
CREATE INDEX epoch_idx on inbound_022018(start_epoch)
更广泛地说,您应该针对具有大量值(不仅仅是1或2种可能性)的列创建索引,并且多列索引可以帮助优化复杂查询。
将EXPLAIN
置于查询之前,并查看特别大的行号的结果,这是确定查询中成本的位置的好方法。通常,有效的索引将解决问题。
答案 1 :(得分:0)
SELECT INTO OUTFILE
不是问题。许多其他事情正在减慢查询速度。
以下是我需要讨论的片段:
FROM inbound_022018 a
LEFT JOIN wireless_checks b ON (a.uuid = b.uuid)
WHERE date(a.start_epoch)='2018-02-19'
AND a.endpoint_disposition='ANSWER'
AND a.direction='inbound'
AND a.billed=1;
`uuid` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(100) NOT NULL ... DEFAULT CHARSET=latin1
float(11,4)
`date` varchar(10) NOT NULL, ...
`ported_date` varchar(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_inbound_0717` (`id`) USING BTREE,
PRIMARY KEY (`id`), ...
UNIQUE KEY `index_all` (`id`,`campaign_id`,`session_id`,`uuid`) USING BTREE,
许多问题:
a.uuid = b.uuid
)时,如果字符集或排序规则不同,则无法使用索引。解决了这个问题。BINARY(16)
。 (代码可在其他地方获得。)a
需要合并INDEX(billed, direction, endpoint_disposition, start_epoch)
才能提高WHERE
的效率。前3列可以按任何顺序排列。PRIMARY KEY
是UNIQUE
键;删除后者。FLOAT(m,n)
是一个无用的结构,因为它涉及两个舍入。对于货币价值,请使用DECIMAL(m,n)
;为科学'值,使用FLOAT
而不使用(m,n)
。b.id
,请摆脱它并宣传uuid
为PK。这将加快InnoDB的JOIN
。当列被隐藏时#39在函数内部(例如,VARCHAR
),索引列无法提供帮助。改为
DATE()
通过此更改,我建议的WHERE a.start_epoch >= '2018-02-19'
AND a.start_epoch < '2018-02-19' + INTERVAL 1 DAY
中的第4列将可用。