我正在寻找合适的解决方案来归档非常大的表(每天大约10000行)。
我现在有这样的情况:
订单表:

CREATE TABLE `tbl_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `idproduct` int(11) NOT NULL DEFAULT '0',
  `iduser` int(11) NOT NULL DEFAULT '0',
  `state` int(11) NOT NULL DEFAULT '0',
  `progressive` int(11) NOT NULL DEFAULT '0',
  `show-voucher` int(11) NOT NULL DEFAULT '0',
  `voucher-custom` int(11) NOT NULL DEFAULT '0',
  `check-validate` int(11) NOT NULL DEFAULT '0',
  `code-order` varchar(8) NOT NULL DEFAULT '',
  `code-product` char(15) NOT NULL DEFAULT '',
  `product-year` int(11) NOT NULL DEFAULT '2017',
  `product-area` char(3) NOT NULL DEFAULT '',
  `payment-type` char(3) NOT NULL DEFAULT '',
  `usr-qnt` int(11) NOT NULL DEFAULT '0',
  `usr-id` char(11) NOT NULL DEFAULT '',
  `usr-cid` char(8) NOT NULL DEFAULT '',
  `usr-ct` char(3) NOT NULL DEFAULT '000',
  `price` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-penale` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-rate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-contanti` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-bonusmalus-rate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-bonusmalus-contanti` decimal(10,2) NOT NULL DEFAULT '0.00',
  `price-incasso-contanti` decimal(10,2) NOT NULL DEFAULT '0.00',
  `rate-qnt` int(11) NOT NULL DEFAULT '0',
  `card-qnt` int(11) NOT NULL DEFAULT '0',

  `grp-user` longtext NOT NULL,
  `grp-price` longtext NOT NULL,
  `grp-item` longtext NOT NULL,
  `grp-element` longtext NOT NULL,

  `bonusmalus-description` varchar(500) NOT NULL,

  `note-s` text NOT NULL ,
  `note-c` text NOT NULL,
  `note-incasso` text NOT NULL,
  `note-interne` text NOT NULL,

  `d-start` date NOT NULL DEFAULT '0000-00-00',
  `d-end` date NOT NULL DEFAULT '0000-00-00',
  `d-create` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-incasso` date NOT NULL DEFAULT '0000-00-00',
  `d-sconf` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-cconf` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-export` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-notify-vote` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `d-lastupdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  PRIMARY KEY (`id`),
  KEY `iduser` (`iduser`),
  KEY `code-order` (`code-order`),
  KEY `code-product` (`code-product`),
  KEY `idproduct` (`idproduct`),
  KEY `state` (`state`),
  KEY `price` (`price`),
  KEY `usr-qnt` (`usr-qnt`),
  KEY `d-expire` (`d-expire`),
  KEY `d-export` (`d-export`),
  KEY `price-bonusmalus-contanti` (`price-bonusmalus-contanti`),
  KEY `price-penale` (`price-penale`),
  KEY `price-bonusmalus-contanti_2` (`price-bonusmalus-contanti`),
  KEY `price-rate` (`price-rate`),
  KEY `price-contanti` (`price-contanti`),
  KEY `show-voucher` (`show-voucher`),
  KEY `voucher-custom` (`voucher-custom`),
  KEY `check-validate` (`check-validate`),
  KEY `progressive` (`progressive`),
  KEY `d-incasso` (`d-incasso`),
  KEY `price-incasso-contanti` (`price-incasso-contanti`),
  KEY `d-notify-vote` (`d-notify-vote`),
  KEY `product-year` (`product-year`),
  KEY `product-area` (`product-area`),
  KEY `d-lastupdate` (`d-lastupdate`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

订单是用户(iduser)对旅游套餐(如booking.com)的请求。
此表每天生成约8000到15000行。
恐怕这张桌子太大了,会出问题的。
我的核心领域是:
ID或代码顺序
idp产品或产品代码(我每年大约有5000种产品)
iduser用户
产品年份(我每年都有不同的产品)
产品区(我总共有20个区域:000001002003…019年)
我在网上看过好几种解决方案,但我不知道哪一种可能是最好的:
1)将主表划分为许多其他子表或许多其他数据库?
前任。
DB-2016.待定订单-1月
DB-2016.TBL U订单-2月
……
DB-2017.TBL U订单-1月
DB-2017.TBL U订单-2月
或者
DB.TBL U订单-2016
DB.TBL U订单-2015
DB.TBL U订单-2014
或者
数据库待定
DB.TBL U订单-产品-区域
或者
数据库待定
DB.TBL U订单-产品-年份
在这种情况下,是否通过工会进行选择?
2)对表进行分区?
哪些字段可以执行?
产品年份?产品区(共20个)?
订单创建日期(D-CREATE)?
凭身份证?
3)碎片?但我不知道是什么…
4)Innodb o Myisam公司?
我仍然可以采用的一种解决方案是将长文本字段拆分为二级表,以减少tbl_顺序的权重:
DB.TBL U订单
db.tbl_order-grp-user(IDorder,数据)
DB.TBL U ORDER-GRP-PRICE(订单,数据)
DB.TBL U ORDER-GRP-项目(IDORDER,数据)
db.tbl_order-grp-element(IDorder,数据)
怀疑:如果我这样做,我已经减少了tbl_order表的重量,但是我没有减少记录的数量。因此,必须对db.tbl_order-grp-user、db.tbl_order-grp-price、db.tbl_order-grp-item、db.tbl_order-grp-elements表进行分区?如果你用的是射程指令?
选择所有数据将是:
Select *,
( SELECT `u`.`data` FROM `db`.`tbl_order-grp-user` as `u` where `u`.`idorder`=`order`.`id`) as `grp-user`,
( SELECT `p`.`data` FROM `db`.`tbl_order-grp-price` as `p` where `p`.`idorder`=`order`.`id`) as `grp-price`,
( SELECT `i`.`data` FROM `db`.`tbl_order-grp-item` as `i` where `i`.`idorder`=`order`.`id`) as `grp-item`
FROM  `db`.`tbl_order` as `order`
WHERE ............

谢谢大家的支持!:-)

最佳答案

新手警报…
INT(3字节)足够时,不要使用MEDIUMINT UNSIGNED(4字节)。查找INT选项的其余部分。
不要盲目地索引每一列。
一定要查看SELECTs以查看哪些组合索引是有益的。查看我的Index Cookbook
不要太担心15K/天——这还不到1/秒。100/秒是潜在问题的第一个临界点。
不要PARTITION。它不是灵丹妙药,通常也没有任何益处。很少有用例。
不要拆分成多个“相同”表。曾经。(好吧,有效的用例很少。)
不要害怕一百万行;要关心十亿行。
不要对可变长度字段使用CHAR;请使用VARCHAR
请考虑使用utf8mb4而不是utf8。utf8mb4符合外部世界对UTF-8的看法,包括emoji和所有中文。
一定要用innodb。周期。完全停止。Myisam要走了;InnoDB在几乎所有方面都一样好或者更好。
考虑更改列名以避免-_是常见的,并避免在忘记backtics时出错。
不要切碎。(这是在多个服务器上分割数据。)这是一个中等大小的表,具有中等大小的流量;需要对具有巨大流量的大表进行分片。
在适当的地方说。例如CHARACTER SET ascii。现在的代码需要9个字节——3个字符*每个字符有3个字节(utf8)的空间。
对于product-area,考虑TINYINT(3) UNSIGNED ZEROFILL——这需要1个字节,并为您重新构造前导零。
考虑一下你是否有一个“自然”的product-area,而不是PRIMARY KEY
一定要告诉我们AUTO_INCREMENT列包含什么。
一定要带着试探性的声明回来。没有他们我无法完成这篇评论。
一定要考虑这是否应该是一张桌子。真的是一个用户只订购一个产品吗?您可能需要一个用户表、一个产品表、一个订单表等。

关于mysql - MySQL:如何处理具有数百万行的表?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43524952/

10-16 13:17