2014-04-04 50 views
0

我運行一個更新語句:如何使用子查詢優化更新語句?

UPDATE ACTION a 
INNER JOIN subscriberinfo s ON a.subscriberId=s.id 
SET a.exceedusage = (SELECT FORMAT(((SUM(dataVolumeDownLink + dataVolumeUpLink))/1048576),2) 
      FROM cdr c 
      WHERE c.msisdn=s.msisdn 
      AND c.eventDate>=a.createdon 
      AND c.eventDate <= a.actionTakenOn) 
WHERE a.remark='Reason : Data limit crossed' 
AND a.exceedusage IS NULL; 

但其採取CDR,因爲表(百萬行)的時間太多。有什麼方法可以重寫此查詢,以便它可以快速工作?

編輯:行動

表結構:

CREATE TABLE `action` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `actionTakenOn` datetime DEFAULT NULL, 
    `actionType` varchar(255) DEFAULT NULL, 
    `cdrCreatedOn` datetime DEFAULT NULL, 
    `cdrEventDate` datetime DEFAULT NULL, 
    `createdOn` datetime DEFAULT NULL, 
    `errorDescription` longtext, 
    `params` longtext, 
    `remark` longtext, 
    `requestedOn` datetime DEFAULT NULL, 
    `status` varchar(255) DEFAULT NULL, 
    `subscriberDetails` longtext, 
    `takenBy` varchar(255) DEFAULT NULL, 
    `subscriberId` bigint(20) DEFAULT NULL, 
    `ticketId` bigint(20) DEFAULT NULL, 
    `dataPlanEndTime` datetime DEFAULT NULL, 
    `dataPlanStartTime` datetime DEFAULT NULL, 
    `dataUsage` bigint(20) DEFAULT NULL, 
    `dataplanName` varchar(255) DEFAULT NULL, 
    `exceedUsage` bigint(20) DEFAULT NULL, 
    `isNotified` bit(1) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `FKAB2F7E36E90F678D` (`subscriberId`), 
    KEY `FKAB2F7E3664633B07` (`ticketId`) 
) ENGINE=MyISAM AUTO_INCREMENT=81534 DEFAULT CHARSET=latin1; 

爲Subscriberinfo:

CREATE TABLE `subscriberinfo` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `imsi` varchar(255) DEFAULT NULL, 
    `simType` varchar(45) DEFAULT NULL, 
    `dataPlanStartTime` datetime DEFAULT NULL, 
    `dataPlanEndTime` datetime DEFAULT NULL, 
    `dataplan` varchar(255) DEFAULT NULL, 
    `status` varchar(255) DEFAULT NULL, 
    `validDays` varchar(255) DEFAULT NULL, 
    `deviceName` varchar(500) DEFAULT NULL, 
    `lastDataPlanUpdatedOn` datetime DEFAULT NULL, 
    `lastDeviceUpdatedOn` datetime DEFAULT NULL, 
    `createdOn` datetime DEFAULT NULL, 
    `dataplanType` varchar(255) DEFAULT NULL, 
    `msisdn` bigint(20) DEFAULT NULL, 
    `dataLeft` bigint(20) DEFAULT NULL, 
    `billingSysDataPlanEndTime` datetime DEFAULT NULL, 
    `billingSysDataPlanStartTime` datetime DEFAULT NULL, 
    `billingSysValidDays` int(11) DEFAULT NULL, 
    `dataUsage` bigint(20) DEFAULT NULL, 
    `planDetail` varchar(255) DEFAULT NULL, 
    `currentSpeedLimit` varchar(255) DEFAULT NULL, 
    `lastBillingSysUpdatedOn` datetime DEFAULT NULL, 
    `lastUpdatedOn` datetime DEFAULT NULL, 
    `deviceType` varchar(255) DEFAULT NULL, 
    `lastImsiUpdatedOn` datetime DEFAULT NULL, 
    `skipCheck` tinyint(1) NOT NULL, 
    `active` tinyint(1) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `msisdn_UNIQUE` (`msisdn`) 
) ENGINE=InnoDB AUTO_INCREMENT=49032 DEFAULT CHARSET=latin1; 

爲CDR:

CREATE TABLE `cdr` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `dataPacketDownLink` bigint(20) DEFAULT NULL, 
    `dataPacketUpLink` bigint(20) DEFAULT NULL, 
    `dataPlanEndTime` datetime DEFAULT NULL, 
    `dataPlanStartTime` datetime DEFAULT NULL, 
    `dataVolumeDownLink` bigint(20) DEFAULT NULL, 
    `dataVolumeUpLink` bigint(20) DEFAULT NULL, 
    `dataplan` varchar(255) DEFAULT NULL, 
    `dataplanType` varchar(255) DEFAULT NULL, 
    `createdOn` datetime DEFAULT NULL, 
    `deviceName` varchar(500) DEFAULT NULL, 
    `duration` int(11) NOT NULL, 
    `effectiveDuration` int(11) NOT NULL, 
    `hour` int(11) DEFAULT NULL, 
    `eventDate` datetime DEFAULT NULL, 
    `msisdn` bigint(20) DEFAULT NULL, 
    `quarter` int(11) DEFAULT NULL, 
    `validDays` int(11) DEFAULT NULL, 
    `dataLeft` bigint(20) DEFAULT NULL, 
    `completedOn` datetime DEFAULT NULL, 
    `causeForRecClosing` bigint(20) DEFAULT NULL, 
    `roaming` tinyint(1) DEFAULT NULL, 
    `servedBSAddress` varchar(255) DEFAULT NULL, 
    `simType` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx_msisdn` (`msisdn`) 
) ENGINE=MyISAM AUTO_INCREMENT=2580713 DEFAULT CHARSET=latin1; 
+0

的任何輸出EXPLAIN上上述查詢的選擇?表結構?指標? – blue

回答

2
UPDATE ACTION a 
    INNER JOIN subscriberinfo s ON a.subscriberId=s.id 
    INNER JOIN (SELECT FORMAT(((SUM(dataVolumeDownLink + dataVolumeUpLink))/1048576),2) as val, 
        msisdn 
        FROM cdr c 
        WHERE 
        c.eventDate>=a.createdon 
        AND c.eventDate <= a.actionTakenOn) sub on sub.msisdn=s.msisdn 
SET a.exceedusage = sub.val 
WHERE a.remark='Reason : Data limit crossed' 
AND a.exceedusage IS NULL; 

我會將子查詢移動到FROM(實際上是FROM中的SELECT和UPDATE部分中的查詢),讓它只執行一次。

+0

@ StanislavL-謝謝你的幫助,但請解釋一下,如果可能的話,爲什麼在內部連接中複製相同內容? – Aamir

+1

爲了避免重新計算每個更新的值。在你的情況下,查詢是爲每一行執行的。 – StanislavL

+0

我收到以下錯誤.. 錯誤代碼:1054 運行此查詢時,'where子句' 中的未知列'a.createdon'。如何刪除它? – Aamir

0

可能將整個事情改爲一系列JOIN。

這不能不說是一個猜測(我不知道你的表是如何團結在一起,因此不能確定在GROUP BY),但也許是這樣的: -

UPDATE ACTION a 
INNER JOIN subscriberinfo s ON a.subscriberId=s.id 
INNER JOIN cdr c ON c.msisdn=s.msisdn AND c.eventDate BETWEEN a.createdon AND a.actionTakenOn 
SET a.exceedusage = FORMAT(((SUM(c.dataVolumeDownLink + c.dataVolumeUpLink))/1048576),2) 
WHERE a.remark='Reason : Data limit crossed' 
AND a.exceedusage IS NULL 
GROUP BY a.subscriberId;