我已将此存储过程从ms sql server 2012迁移到mysql集群。
CREATE DEFINER = 'root'@'%'
PROCEDURE get_activeSub(IN p_top int, IN p_carrierid int, IN p_mode int)
BEGIN
DECLARE v_tomorrow datetime;
DECLARE v_temp int;
DECLARE v_sysdate datetime;
SET v_tomorrow = DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY);
IF (p_mode IS NULL) THEN
SET p_mode = 0;
END IF;
IF ((p_mode != 0) AND (p_mode != 1)) THEN
SET p_mode = 0;
END IF;
IF (p_mode = 0) THEN
SET v_sysdate = SYSDATE();
SELECT
activeSub.*
FROM
(
SELECT
-- e.msisdn
-- ,e.hasCredit
-- ,e.lastBillingDate
-- ,
MIN(a.schedulingId) AS schedulingIdMin
FROM
activeSub a
LEFT OUTER JOIN endUser e /*force INDEX for ORDER BY (IDX_enduser_lastBillingDate)*/ ON e.endUserId = a.endUserId
INNER JOIN smartBillingInterval sb ON a.serviceId = sb.serviceId AND sb.transactionTypeId = 7
WHERE
(a.stateId IN (2000, 2007, 2008) OR a.stateid IS NULL)
AND a.nextBillingDate < v_tomorrow
AND a.carrierId = p_carrierId
AND (a.numRetry IS NULL OR a.numRetry <= sb.maxRetry_full)
AND (a.lastBillingPrice IS NULL OR (a.lastBillingPrice = sb.price_full AND a.nextBillingDate < v_sysdate))
GROUP BY
e.enduserid
-- ,e.hasCredit
-- ,e.lastBillingDate
ORDER BY
e.hasCredit DESC
,e.lastBillingDate DESC
LIMIT p_top
) aGrouped INNER JOIN activeSub ON activeSub.schedulingId = aGrouped.schedulingIdMin
ORDER BY activeSub.numRetry;
ELSE
SELECT
COUNT(*)
FROM (SELECT
COUNT(*) AS QUANTITY
FROM activeSub a
left outer join endUser e
ON e.endUserId = a.endUserId
INNER JOIN smartBillingInterval sb
ON a.serviceId = sb.serviceId AND sb.transactionTypeId = 7
-- where stateId not in (71010,21010) and nextBillingDate<@tomorrow and a.carrierId=@carrierId
WHERE (stateId IN (2000, 2007, 2008) OR stateid IS NULL)
AND nextBillingDate < v_tomorrow
AND a.carrierId = p_carrierId
-- NUMRETRY IN INTERVALS
AND (numRetry IS NULL OR numRetry <= sb.maxRetry_full)
-- NEXT PRICE TO USE, TAKING CARE ABOUT SHORT-RETRIES FOR FULL PRICES SWEPT
AND (lastBillingPrice IS NULL OR (lastBillingPrice = sb.price_full AND nextBillingDate < SYSDATE()))
GROUP BY e.msisdn,
e.hasCredit,
e.lastBillingDate) AS Q;
END IF;
END
i call them with call get_activesub(300,101101,0)
the structure of tables involved are
USE lisabel;
CREATE TABLE lisabel.activesub (
endUserId bigint(20) NOT NULL,
serviceId int(11) NOT NULL,
carrierId int(11) NOT NULL,
shortCodeId int(11) DEFAULT NULL,
schedulingId bigint(20) NOT NULL,
pendingDate datetime DEFAULT NULL,
subscriptionDate datetime DEFAULT NULL,
firstBillingDate datetime DEFAULT NULL,
numBilling int(11) DEFAULT NULL,
numCredits int(11) DEFAULT NULL,
originId int(11) NOT NULL,
text varchar(160) DEFAULT NULL,
hierarchyId int(11) DEFAULT NULL,
subscriptionHierarchyId int(11) NOT NULL,
contentId bigint(20) DEFAULT NULL,
moId bigint(20) DEFAULT NULL,
channel varchar(100) DEFAULT NULL,
pinCode varchar(4) DEFAULT NULL,
transactionId bigint(20) DEFAULT NULL,
nextBillingDate datetime DEFAULT NULL,
deliveryReportId int(11) DEFAULT NULL,
retCode varchar(255) DEFAULT NULL,
numRetry int(11) DEFAULT NULL,
numShortRetry int(11) DEFAULT NULL,
stateId int(11) DEFAULT NULL,
previousStateId int(11) DEFAULT NULL,
page varchar(100) DEFAULT NULL,
handsetId int(11) DEFAULT NULL,
lastBillingDate datetime DEFAULT NULL,
banningCount int(11) DEFAULT NULL,
flowId int(11) DEFAULT NULL,
subscriptionNumRetry int(11) DEFAULT NULL,
subscriptionNumShortRetry int(11) DEFAULT NULL,
debit int(11) DEFAULT NULL,
partnerNotificationMask varchar(10) DEFAULT NULL,
lastBillingPrice decimal(10, 2) DEFAULT NULL,
sessionId bigint(20) DEFAULT NULL,
gclid varchar(50) DEFAULT NULL,
msisdn varchar(50) DEFAULT NULL,
PRIMARY KEY (endUserId, serviceId),
INDEX FK_activeSub_content USING BTREE (contentId),
INDEX FK_activeSub_deliveryReport USING BTREE (deliveryReportId),
INDEX FK_activeSub_handset USING BTREE (handsetId),enter code here
INDEX FK_activeSub_hierachy USING BTREE (hierarchyId),
INDEX FK_activeSub_origin USING BTREE (originId),
INDEX FK_activeSub_shortCode USING BTREE (shortCodeId),
INDEX FK_activeSub_subscriptionHierarchy USING BTREE (subscriptionHierarchyId),
INDEX IDX_activesub_carrierId USING BTREE (carrierId),
INDEX IDX_activesub_endUserId USING BTREE (endUserId),
INDEX IDX_activesub_lastBillingPrice USING BTREE (lastBillingPrice),
INDEX IDX_activesub_nextBillingDate USING BTREE (nextBillingDate),
INDEX IDX_activesub_numRetry USING BTREE (numRetry),
INDEX IDX_activesub_schedulingId USING BTREE (schedulingId),
INDEX IDX_activesub_serviceId USING BTREE (serviceId),
INDEX IDX_activesub_stateId USING BTREE (stateId)
)
ENGINE = NDBCLUSTER
AVG_ROW_LENGTH = 204
CHARACTER SET latin1
COLLATE latin1_swedish_ci;
USE lisabel;
CREATE TABLE lisabel.enduser (
endUserId bigint(20) NOT NULL AUTO_INCREMENT,
msisdn varchar(50) NOT NULL,
carrierId int(11) NOT NULL,
handsetId int(11) DEFAULT NULL,
hasCredit bit(1) DEFAULT NULL,
lastBillingDate datetime DEFAULT NULL,
lastAttemptDate datetime DEFAULT NULL,
PRIMARY KEY (endUserId),
INDEX FK_endUser_handset USING BTREE (handsetId),
INDEX FK_endUsers_carrier USING BTREE (carrierId),
INDEX IDX_enduser_endUserId USING BTREE (endUserId),
INDEX IDX_enduser_lastBillingDate USING BTREE (lastBillingDate),
UNIQUE INDEX IDX_enduser_msisdn USING BTREE (msisdn)
)
ENGINE = NDBCLUSTER
AUTO_INCREMENT = 2040353
AVG_ROW_LENGTH = 60
CHARACTER SET latin1
COLLATE latin1_swedish_ci;
这两个表都是内存中的表。 table activesub有300.000条记录,enduser表有2.000.000条记录。 如果我运行解释扩展
EXPLAIN EXTENDED
SELECT
activeSub.*
FROM
(`enter code here`
SELECT
-- e.msisdn
-- ,e.hasCredit
-- ,e.lastBillingDate
-- ,
MIN(a.schedulingId) AS schedulingIdMin
FROM
activeSub a
LEFT OUTER JOIN endUser e USE INDEX for ORDER BY (IDX_enduser_lastBillingDate) ON e.endUserId = a.endUserId
INNER JOIN smartBillingInterval sb ON a.serviceId = sb.serviceId AND sb.transactionTypeId = 7
WHERE
(a.stateId IN (2000, 2007, 2008) OR a.stateid IS NULL)
AND a.nextBillingDate < '2014-12-15'
AND a.carrierId = 101101
AND (a.numRetry IS NULL OR a.numRetry <= sb.maxRetry_full)
AND (a.lastBillingPrice IS NULL OR (a.lastBillingPrice = sb.price_full AND a.nextBillingDate < sysdate()))
GROUP BY
e.enduserid
-- ,e.hasCredit
-- ,e.lastBillingDate
ORDER BY
e.hasCredit DESC
,e.lastBillingDate DESC
LIMIT 300
) aGrouped INNER JOIN activeSub ON activeSub.schedulingId = aGrouped.schedulingIdMin
ORDER BY activeSub.numRetry;
SHOW WARNINGS;
结果是:
1 PRIMARY <derived2> ALL (null) (null) (null) (null) 300 100 Using where; Using temporary; Using filesort
1 PRIMARY activeSub ref IDX_activesub_schedulingId IDX_activesub_schedulingId 8 aGrouped.schedulingIdMin 1 100 (null)
2 DERIVED a ref IDX_activesub_stateId,IDX_activesub_lastBillingPrice,IDX_activesub_numRetry,IDX_activesub_nextBillingDate,IDX_activesub_carrierId,IDX_activesub_serviceId IDX_activesub_carrierId 4 const 305303 100 Parent of 3 pushed join@1; Using where with pushed condition (((`lisabel`.`a`.`stateId` in (2000,2007,2008)) or isnull(`lisabel`.`a`.`stateId`)) and (`lisabel`.`a`.`nextBillingDate` < '2014-12-15')); Using temporary; Using filesort
2 DERIVED sb eq_ref PRIMARY PRIMARY 8 lisabel.a.serviceId,const 1 100 Child of 'a' in pushed join@1; Using where
2 DERIVED e eq_ref PRIMARY,IDX_enduser_endUserId PRIMARY 8 lisabel.a.endUserId 1 100 Child of 'a' in pushed join@1; Using where
工作台执行计划是:
执行时间为2.5 - 3秒。如何改善执行时间?