从mysql获取大结果集

时间:2014-03-16 23:03:25

标签: php mysql sql bigtable

我有一个大约有2000万行的大表,每天都会长大,我有一个从这个表中查询的表单。不幸的是,查询返回了数十万行。 查询基于时间,我需要所有记录根据一些规则通过'clid'对它们进行分类。所以我需要所有记录对它们进行一些处理以制作结果表。 这是我的表:

    CREATE TABLE IF NOT EXISTS `cdr` (
  `gid` bigint(20) NOT NULL AUTO_INCREMENT,
  `prefix` varchar(20) NOT NULL DEFAULT '',
  `id` bigint(20) NOT NULL,
  `start` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `clid` varchar(80) NOT NULL DEFAULT '',
  `duration` int(11) NOT NULL DEFAULT '0',
  `service` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`gid`),
  UNIQUE KEY `id` (`id`,`prefix`),
  KEY `start` (`start`),
  KEY `clid` (`clid`),
  KEY `service` (`service`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf-8 ;

这是我的疑问:

SELECT * FROM `cdr` 
    WHERE 
        service = 'test' AND 
        `start` >= '2014-02-09 00:00:00' AND 
        `start` < '2014-02-10 00:00:00' AND 
        `duration` >= 10

日期可能从1小时到60天甚至更长。(如:

  

DATE(start)BETWEEN'2013-02-02 00:00:00'''2014-02-03 00:00:00'

结果集每天大约有150,000行。当我试图获得更长时间的结果甚至一天数据库崩溃。 有人有任何想法吗?

1 个答案:

答案 0 :(得分:3)

我不知道如何防止它崩溃,但我对大表做的一件事就是按日期对它们进行分区。

在这里,我按日期对行进行分区,每月两次。只要您的查询使用分区列,它就只会搜索包含密钥的分区。它不会进行全表扫描。

CREATE TABLE `identity` (
  `Reference` int(9) unsigned NOT NULL AUTO_INCREMENT,
  ...
  `Reg_Date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`Reference`),
  KEY `Reg_Date` (`Reg_Date`)
) ENGINE=InnoDB AUTO_INCREMENT=28424336 DEFAULT CHARSET=latin1
PARTITION BY RANGE COLUMNS (Reg_Date) (

  PARTITION p20140201 VALUES LESS THAN ('2014-02-01'),
  PARTITION p20140214 VALUES LESS THAN ('2014-02-14'),
  PARTITION p20140301 VALUES LESS THAN ('2014-03-01'),
  PARTITION p20140315 VALUES LESS THAN ('2014-03-15'),
  PARTITION p20140715 VALUES LESS THAN (MAXVALUE)

);

基本上,你只需要对表进行转储,使用分区创建它,然后将数据导入其中。