加入具有小表索引的大表

时间:2016-10-31 14:14:06

标签: mysql join

我在MySql数据库中有一个名为event的大表,有1000万条记录。

事件

CREATE TABLE `event` (
    `eventId` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `eventTime` BIGINT(20) NOT NULL COMMENT 'ex: 1431201865000 (epoch is milliseconds)',
    `sourceId` BIGINT(20) NOT NULL COMMENT 'ex: pole-code: 1 = JA005, patrolCarCode: 5000 = D4588',
    PRIMARY KEY (`eventId`),
    INDEX `eventTime` (`eventTime`),
    INDEX `sourceId` (`sourceId`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=12343262;

我的小桌子有大约70条记录。

来源

CREATE TABLE `source` (
    `sourceId` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `sourceName` VARCHAR(100) NOT NULL COMMENT 'ex: pole-code: JA005, patrolCarCode:D4588' COLLATE 'utf8_unicode_ci',
    `sourceGps` VARCHAR(40) NULL DEFAULT NULL COMMENT 'Only for Fixed source (Poles) ex: 25.110227 N  55.239798 E, 24.993183 N  55.250382 E, 0.000000 N  0.000000 E' COLLATE 'utf8_unicode_ci',
    `sourceAddress` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Only for Fixed source (Poles) ex: Dubai, Bur Dubai, Burjman Center Interchange' COLLATE 'utf8_unicode_ci',
    `sourceAltAddress` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Alternative address, ex: address in arabic' COLLATE 'utf8_unicode_ci',
    PRIMARY KEY (`sourceId`),
    INDEX `sourceName` (`sourceName`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=71
;

数据

INSERT INTO `event` (`eventId`, `eventTime`, `sourceId`) VALUES
    ( 1474261476616, 33, 1),
    ( 1474261438966, 26, 2),
    ( 1474261479346, 25, 3),
    ( 1474261429952, 8, 5),
    ( 1474261477316, 33, 6)

INSERT INTO `source` (`sourceId`, `sourceName`, `sourceGps`, `sourceAddress`) VALUES
    ( 1, 'JA001', '25.110227 N  55.239798 E', 'Interchange'),
    ( 2, 'JA002', '25.110227 N  55.239798 E', 'Interchange'),
    ( 3, 'JA003', '25.110227 N  55.239798 E', 'Interchange'),
    ( 4, 'JA004', '25.110227 N  55.239798 E', 'Interchange'),
    ( 5, 'JA005', '25.110227 N  55.239798 E', 'Interchange')

任务

我想知道在特定时间之后发生的所有事件' 1474261429952'。

搜索到目前为止我已经制定了以下查询,这会带来结果,但速度很慢。 从表中检索结果大约需要1.5分钟。

SELECT count(source.sourceId) as 'totalEvents', source.sourceId, source.sourceGps, 
source.sourceAddress  from event  inner join source on event.sourceId = source.sourceId  
where eventTime >= 1474261429952 group by source.sourceId

解释结果:

Here is explain result

请指导我如何加快速度。

感谢。

2 个答案:

答案 0 :(得分:0)

您应该向events表添加一个多列索引,涵盖字段sourceid, eventtime(按此特定顺序)。

原因:MySQL可以在查询中为每个表使用一个索引(嗯,索引合并是一个小例外)。您在sourceid, eventtime字段上有单独的索引,MySQL确实考虑使用这些索引,但是将它们解除(请参阅解释结果中的可能键和关键字段) - 可能单独使用它们都不够具有选择性。

通过另一个explain创建索引后检查索引使用情况。您可能必须使用索引提示(use indexforce index)来使MySQL使用新索引,尽管analyse table也可能有助于此。

答案 1 :(得分:0)

虽然Shadow指出了多个字段索引与个人的问题,但我建议使用(eventtime,sourceid)的不同顺序而不是(sourceid,eventtime)。原因是...如果您的数据是10年,您仍然必须经历从旧到现在的每个来源。而不是仅仅跳到当前的日期范围。此外,您不是使用SOURCE表而不是EVENT进行分组,而是利用事件的索引,因为无论如何它们的键都是相同的。

由于来源是

SELECT 
      count(*) as 'totalEvents', 
      source.sourceId, 
      source.sourceGps, 
      source.sourceAddress  
   from 
      event  
         inner join source 
            on event.sourceId = source.sourceId
   where 
      eventTime >= 1474261429952 
   group by 
      event.sourceId

如果你想尝试使用基于(SourceID,EventTime)的索引,我会改变查询并将SOURCE表放在第一个位置并写为......有趣的是你得到的时间性能差异回来。

SELECT 
      S.sourceId, 
      S.sourceGps, 
      S.sourceAddress,
      count(*) as totalEvents
   from 
      source S
         join event E
            on S.sourceId = E.sourceId
           AND E.eventTime >= 1474261429952
   group by 
      S.sourceId