我正在开发由php,laravel framework,mariadb编写的仓库控制系统。要获得有关每种产品的所有信息,我们会使用产品"历史"表,记录对特定产品采取的所有操作。这个表开始快速扩展,现在我们有大约1500万行innoDB表开始工作缓慢,特别是在运行功能时,需要全面分析销售,创建,丢弃等产品的数量,然后需要全部1500万行在一个查询..所以我开始搜索方式,如何管理这个大表,因为索引不再工作。 我开始考虑按日期拆分/分区这个表,也许是行动?所以也许任何人都有这方面的经验并可以与我分享一些建议?非常感谢任何帮助!
CREATE TABLE `history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`barcode` varchar(100) DEFAULT NULL,
`bag` varchar(100) DEFAULT NULL,
`action` int(10) unsigned DEFAULT NULL,
`place` int(10) unsigned DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
`old_price` decimal(10,2) DEFAULT NULL,
`user` int(11) DEFAULT NULL,
`amount` int(10) DEFAULT NULL,
`rotation` int(10) unsigned DEFAULT NULL,
`discount` decimal(10,2) DEFAULT NULL,
`discount_type` tinyint(2) unsigned DEFAULT NULL,
`original` int(10) unsigned DEFAULT NULL,
`was_in_shop` int(10) unsigned DEFAULT NULL,
`cate` int(10) unsigned DEFAULT NULL COMMENT 'grupe',
`sub_cate` int(10) unsigned DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
`helper` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `barcode` (`barcode`),
KEY `action` (`action`),
KEY `original` (`original`),
KEY `created_at` (`created_at`),
KEY `bag` (`bag`)
) ENGINE=InnoDB AUTO_INCREMENT=16274267 DEFAULT CHARSET=utf8
例如查询:
select cate,
SUM(amount) AS amount, SUM(IF(discount>0,(price*amount)-discount,
(price*amount))) AS sum, SUM(IF(discount>0,IF(discount_type=1,
(discount*price)/100,discount),0)
) AS discount from history
where (history.action = '4'
and history.created_at >= '2017-11-01 00:00:00'
and history.created_at <= '2017-11-23 23:59:59'
)
and LENGTH(barcode) > 7
and history.deleted_at is null
group by cate
此查询用于获取有关已售产品的金额,金额,折扣信息(操作4)在此示例中,它是2017-11-01和2017-11-23之间的信息,EXPLAIN
给我这样的信息:
id - 1
select_type - SIMPLE
table - history
type - ref
possible_keys - action,created_at
key - action
key_len - 5
ref - const
rows - 1444272
Extra - Using where; Using temporary; Using filesort
所以它需要150万行,表格保存2017-01-01至今的数据,因此2年后需要300万行等...当我需要只需2017-11产品时出售信息。我有很多类似的问题。
答案 0 :(得分:0)
INT
占用4个字节;其他尺寸可供选择。PARTITIONing
不本质上提供任何表现。history.deleted_at is null
- 考虑实际删除行。INDEX(action, created_at)
。 (一次只使用一个索引。)通过构建和维护汇总表来实现重大改进;见http://mysql.rjweb.org/doc.php/summarytables。然后针对它们运行查询。大多数指数都可以消失。
修复其中一些;那我可以帮你进一步。
更多强>
评论询问如何以两种不同的方式维护摘要表ID。两者都可行,取决于更多,尚未具体说明的细节:
INSERT INTO Fact
表,并立即使用IODKU插入或更新Summary表。INSERT .. SELECT ..
以捕获尚未汇总的行,并将计数/小计放入摘要表中。 后一种选择有效,但有两点需要注意:
PRIMARY KEY
,例如日期(日期或小时)和几个维度值,那么您就会遇到INSERT
问题。要么避免将其作为PK(从而导致多行,这不是'坏'),要么使用INSERT ... ON DUPLICATE KEY ... SELECT ... GROUP BY ...;
形式的IODKU并使用VALUES(xx)
函数。