MySQL - 优化查询

时间:2014-02-04 04:59:49

标签: mysql sql query-optimization

我留下的报告以非常慢的速度返回行。我觉得我需要在没有这么多或任何子查询的情况下重做。但是我对如何尝试这个问题进行了彻底的大脑冻结。

我查看了索引,并且键不够独特,这会强制全表扫描时间。有没有什么办法可以使用单独的查询从其他表中提取某些信息,将其添加为变量并在主查询中使用它。实际上,这个查询的结果只有几行。

是否有任何提示或技巧,我可以使用它来优化或更正此SQL语句以加快速度。

(编辑)我已经为表添加了一些创建代码。

SELECT
     case when (select count(ag.`PKEY`) - count(ag.`ANSWERTIME`)  from acdcallinformation ag
     where (ag.`COMPLETED`) = 1 and answertime is null and time(ag.INSTIME) and DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now()) and ag.skillid = acdcallinformation.skillid) is null
        then 0
            else
        (select count(ag.`PKEY`) - count(ag.`ANSWERTIME`)  from acdcallinformation ag where (ag.`COMPLETED`) = 1
        and answertime is null and DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now()) and ag.skillid = acdcallinformation.skillid)
     end as LostCalls,
     case when count(acdcallinformation.idleonqueue) is null then 0 else count(acdcallinformation.idleonqueue) end as CountCallsACD,
     case when count(acdcallinformation.`ANSWERTIME`) is null then 0 else count(acdcallinformation.`ANSWERTIME`) end AS acdcallinformation_ANSWERED,
     (select skillinfo.skillname from skillinfo where skillinfo.pkey = acdcallinformation.skillid) AS acdcallinformation_SKILLIDTEXT,

     (select count(pkey) from acdcallinformation age
       where DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now()) and age.skillid = acdcallinformation.skillid and   (age.`COMPLETED`) = 0 and answertime is null
        and SKILLID in (select SKILLID
                                from
                            callcenterinformation
                            where time > (now() - INTERVAL 5 SECOND) and callswaiting > 0)) as Waiting,

     -- count(acdcallinformation.`PKEY`) as CallsWaiting,
     acdcallinformation.`DATEOFCALL` AS acdcallinformation_DATEOFCALL,
     acdcallinformation.`FIRSTRINGONQUEUE` AS acdcallinformation_FIRSTRINGONQUEUE,
     case when acdcallinformation.`CONNECTTIME` is null then time('00:00:00') else acdcallinformation.`CONNECTTIME` end AS acdcallinformation_CONNECTTIME,
     acdcallinformation.`CALLSTATEBEFOREIDLE` AS acdcallinformation_CALLSTATEBEFOREIDLE,
     case when acdcallinformation.`AGENTRINGTIME` is null then time('00:00:00') else acdcallinformation.`AGENTRINGTIME` end AS acdcallinformation_AGENTRINGTIME,
     acdcallinformation.`IDLEONQUEUE` AS acdcallinformation_IDLEONQUEUE,
     acdcallinformation.`DDI` AS acdcallinformation_DDI,
     acdcallinformation.`CLIP` AS acdcallinformation_CLIP,
     acdcallinformation.`SKILLID` AS acdcallinformation_SKILLID,
     acdcallinformation.`ACTIONTYPE` AS acdcallinformation_ACTIONTYPE,
     acdcallinformation.`ACTIONDESTINATION` AS acdcallinformation_ACTIONDESTINATION,
     acdcallinformation.`COMPLETED` AS acdcallinformation_COMPLETED,
     acdcallinformation.`HANDLED` AS acdcallinformation_HANDLED,
     acdcallinformation.`CONFIRMED` AS acdcallinformation_CONFIRMED,
    (
        SELECT
         cal.`AGENTSREADY` AS callcenterinformation_AGENTSREADY
    FROM
         `callcenterinformation` cal
    WHERE cal.skillid <> 1 and acdcallinformation.skillid = skillid order by pkey desc limit 1,1) as agentsready
FROM
     `acdcallinformation` acdcallinformation
where DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now()- interval 1 day )
group by (select skillinfo.skillname from skillinfo where skillinfo.pkey = acdcallinformation.skillid);


CREATE TABLE `callcenterinformation` (
    `INSTIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `PKEY` INT(11) NOT NULL,
    `SKILLID` INT(11) NULL DEFAULT '0',
    `DATE` DATE NULL DEFAULT NULL,
    `TIME` TIME NULL DEFAULT NULL,
    `AGENTSLOGGEDIN` INT(11) NULL DEFAULT '0',
    `AGENTSREADY` INT(11) NULL DEFAULT '0',
    `AGENTSRINGING` INT(11) NULL DEFAULT '0',
    `AGENTSCONNECTED` INT(11) NULL DEFAULT '0',
    `AGENTSINPAUSE` INT(11) NULL DEFAULT '0',
    `AGENTSINWRAPUP` INT(11) NULL DEFAULT '0',
    `CALLSWAITING` INT(11) NULL DEFAULT '0',
    `COMPLETED` TINYINT(1) NULL DEFAULT '0',
    `HANDLED` TINYINT(1) NULL DEFAULT '0',
    `CONFIRMED` TINYINT(1) NULL DEFAULT '0',
    PRIMARY KEY (`PKEY`),
    INDEX `DATE` (`DATE`),
    INDEX `TIME` (`TIME`),
    INDEX `SKILLID` (`SKILLID`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;


CREATE TABLE `acdcallinformation` (
    `INSTIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `PKEY` INT(11) NOT NULL,
    `DATEOFCALL` DATE NULL DEFAULT NULL,
    `FIRSTRINGONQUEUE` TIME NULL DEFAULT NULL,
    `CONNECTTIME` TIME NULL DEFAULT NULL,
    `CALLSTATEBEFOREIDLE` INT(11) NULL DEFAULT '0',
    `AGENTRINGTIME` TIME NULL DEFAULT NULL,
    `ANSWERTIME` TIME NULL DEFAULT NULL,
    `IDLEONQUEUE` TIME NULL DEFAULT NULL,
    `DDI` TEXT NULL,
    `CLIP` TEXT NULL,
    `SKILLID` INT(11) NULL DEFAULT '0',
    `ACTIONTYPE` INT(11) NULL DEFAULT '0',
    `ACTIONDESTINATION` TEXT NULL,
    `COMPLETED` TINYINT(1) NULL DEFAULT '0',
    `HANDLED` TINYINT(1) NULL DEFAULT '0',
    `CONFIRMED` TINYINT(1) NULL DEFAULT '0',
    PRIMARY KEY (`PKEY`),
    INDEX `DATEOFCALL` (`DATEOFCALL`),
    INDEX `IDLEONQUEUE_HANDLED` (`IDLEONQUEUE`, `HANDLED`),
    INDEX `SKILLID` (`SKILLID`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;


CREATE TABLE `skillinfo` (
    `INSTIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `PKEY` INT(11) NOT NULL,
    `SKILLNAME` TEXT NULL,
    `CLIP` TEXT NULL,
    `WRAPUPTIMELENGTH` INT(11) NULL DEFAULT '0',
    `MAXRINGTIMELENGTH` INT(11) NULL DEFAULT '0',
    `FORCEDTICKET` TINYINT(1) NULL DEFAULT '0',
    `STATEAFTERWRAPUP` INT(11) NULL DEFAULT '0',
    `STATEAFTERUNANSWEREDCALL` INT(11) NULL DEFAULT '0',
    `ACTIONTYPE` INT(11) NULL DEFAULT '0',
    `ACTIONDESTINATION` TEXT NULL,
    `DEFLECTAFTERCOURTESY` TINYINT(1) NULL DEFAULT '0',
    `MAXOVERALLRINGTIMELENGTH` INT(11) NULL DEFAULT '0',
    `AUTOCLIP` TINYINT(1) NULL DEFAULT '0',
    `OUTGOINGSETTINGSACTIVE` TINYINT(1) NULL DEFAULT '0',
    `NUMPLANIDENTIFIER` INT(11) NULL DEFAULT '0',
    `TYPEOFNUMBER` INT(11) NULL DEFAULT '0',
    `CLIR` INT(11) NULL DEFAULT '0',
    `OUTGOINGROUTEID` INT(11) NULL DEFAULT '0',
    `USELASTAGENT` TINYINT(1) NULL DEFAULT '0',
    `CLIPROUTINGACTIVE` TINYINT(1) NULL DEFAULT '0',
    `USETHRESHOLD` TINYINT(1) NULL DEFAULT '0',
    `NORMALLOADTHRESHOLD` INT(11) NULL DEFAULT '0',
    `OVERLOADTHRESHOLD` INT(11) NULL DEFAULT '0',
    `STATEAFTERFORWARD` INT(11) NULL DEFAULT '0',
    `CALLDISTTYPE` INT(11) NULL DEFAULT '0',
    `USERGROUPID` INT(11) NULL DEFAULT '0',
    `EXTERNALCONTROL` TINYINT(1) NULL DEFAULT '0',
    `LASTAGENTLIMIT` INT(11) NULL DEFAULT '0',
    PRIMARY KEY (`PKEY`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;

1 个答案:

答案 0 :(得分:1)

老实说,这个查询有太多“错误”,它不再有趣了= /

一些想法:

  • IFNULL()CASE WHEN <field> IS NULL THEN constant ELSE <field> END更具可读性,特别是如果原来是一个子查询。
  • AFAIK COUNT(*)将始终返回0,即使找不到任何内容。因此,不需要在它周围写一个IFNULL()
  • COUNT(field)只计算此字段的非NULL记录,但同样,如果没有找到任何内容,它将返回0,因此不需要围绕它的IFNULL()
  • 你应该教会自己JOIN表格如何(更好)比在整个地方使用相关子查询更好。
  • 我对mysql知之甚少,但在我看来,你通过在那些似乎有一个有用索引的字段周围放置强制转换和函数来杀死你的性能。我很确定由于这些结构,引擎根本无法使用所述索引导致性能下降。例如。我会尝试改写
    • AND DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now())AND DATEOFCALL >= CUR_DATE()之类的东西,毕竟双方都是日期(=数字)
    • 出于同样的原因,
    • DATE_FORMAT(DATEOFCALL,'%Y-%m-%d') >= date(now()- interval 1 day)进入DATEOFCALL >= date(now()- interval 1 day)
    • 我也不确定time(ag.INSTIME)应该做什么?!?!只要时间与00:00:00不同,是真的吗?
  • 我非常惊讶这个查询实际上只是GROUP BY上的skillname编译,但也从表中获取了很多其他字段(例如{{1} })。从一个不应该工作的MSSQL背景..我猜mysql是不同的,虽然我不知道结果会是什么样。

无论如何,尝试将以上某些内容应用于您的查询我最终会在下面结束。我怀疑它会“快得多”;它可能只是一点点,但我认为它是你的任务中向前迈进一步,以进一步清理它......

祝你好运!

idleonqueue