具有subselect group by和order by的Mysql Cluster存储过程很慢

时间:2014-12-11 10:22:57

标签: mysql cluster-computing

我已将此存储过程从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

工作台执行计划是:

enter image description here

执行时间为2.5 - 3秒。如何改善执行时间?

0 个答案:

没有答案