优化 mysql 架构,需要建议
Posted
技术标签:
【中文标题】优化 mysql 架构,需要建议【英文标题】:optimize mysql schema, need advice 【发布时间】:2013-01-02 00:52:45 【问题描述】:我被要求帮助检查表格并提高性能。 该表是一个有 2.000.000 行的大表,并且正在快速增长。 有很多用户正在使用此表进行大量更新/插入和删除查询。
也许你可以给我一些好的建议来提高性能和真实性
这是表定义:
创建表`计算`( `GROUP_LINE_ID` BIGINT(250) NOT NULL DEFAULT '0', `GROUP_LINE_PARENT_ID` BIGINT(250) NOT NULL DEFAULT '0', `MOEDER_LINE_CODE` BIGINT(250) NOT NULL DEFAULT '0', `CALC_ID` BIGINT(250) NOT NULL DEFAULT '0', `GROUP_ID` BIGINT(250) NOT NULL DEFAULT '0', `CODE` VARCHAR(250) 默认为空, `DESCRIPTION` VARCHAR(250) 默认空值, `RAW_AMOUNT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `AMOUNT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `UNIT` VARCHAR(100) 默认为空, `MEN_HOURS` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `PRICE_PER_UNIT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `CONTRACTOR_UNIT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `POSTS_PER_UNIT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `SORT_INDEX` BIGINT(250) NOT NULL DEFAULT '0', `FACTOR` DECIMAL(50,4) NOT NULL DEFAULT '0.0000', `FACTOR_TYPE` INT(2) NOT NULL DEFAULT '0', `ROUND_AT` DECIMAL(50,2) NOT NULL DEFAULT '0.00', `MATERIAL_ID` BIGINT(250) NOT NULL DEFAULT '0', `MINIMUM` DECIMAL(50,2) NOT NULL DEFAULT '0.00', `LINE_TYPE` INT(1) NOT NULL DEFAULT '0', `ONDERDRUKT` INT(5) NOT NULL DEFAULT '0', `MARKED` INT(5) NOT NULL DEFAULT '0', `IS_TEXT` INT(5) NOT NULL DEFAULT '0', `BRUTO_PRICE` DECIMAL(20,2) NOT NULL DEFAULT '0.00', `AMOUNT_DISCOUNT` DECIMAL(20,3) NOT NULL DEFAULT '0.000', `FROM_CONSTRUCTOR` INT(5) NOT NULL DEFAULT '0', `CHANGE_DATE` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', `BEREKENING_VALUE` INT(5) NOT NULL DEFAULT '0', `MAATVOERING_ID` BIGINT(250) NOT NULL DEFAULT '0', `KOZIJN_CALC_ID` BIGINT(250) NOT NULL DEFAULT '0', `IS_KOZIJN_CALC_TOTALS` INT(5) NOT NULL DEFAULT '0', `EAN_CODE` VARCHAR(150) 默认为空, `UURLOON_ID` BIGINT(20) NOT NULL DEFAULT '0', `ORG_PRICE_PER_UNIT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `ORG_CONTRACTOR_UNIT` DECIMAL(50,3) NOT NULL DEFAULT '0.000', `BTWCode` INT(5) NOT NULL DEFAULT '0', `IS_CONTROLE_GETAL` INT(5) NOT NULL DEFAULT '0', `AttentieRegel` INT(5) NOT NULL DEFAULT '0', `KozijnSelectionRowId` BIGINT(250) NOT NULL DEFAULT '0', `OfferteTekst` 文本, `VerliesFactor` DECIMAL(15,4) NOT NULL DEFAULT '0.0000', 主键(`GROUP_LINE_ID`), KEY `GROUP_LINE_PARENT_ID`(`GROUP_LINE_PARENT_ID`), KEY `MOEDER_LINE_CODE`(`MOEDER_LINE_CODE`), KEY `CALC_ID`(`CALC_ID`), KEY `GROUP_ID`(`GROUP_ID`), KEY `MATERIAL_ID`(`MATERIAL_ID`), KEY `MAATVOERING_ID`(`MAATVOERING_ID`), KEY `KOZIJN_CALC_ID`(`KOZIJN_CALC_ID`), 键 `IS_KOZIJN_CALC_TOTALS` (`IS_KOZIJN_CALC_TOTALS`) ) 引擎=MyISAM 默认字符集=utf8;在我看来
将表引擎更改为 InnoDB bigint(250) 可以改成 bigint(10) 的 int(10) 吗?请给我一些建议
【问题讨论】:
因为 int 是 4 位而 bigint 是 8 位我猜 int(4) 和 bigint(8) 是最大值吗? 【参考方案1】:是的,你是对的..
1.请记住,表中的主键是在所有其他键的最后分配的 所以保持你的主键尽可能小我认为 int 就足够了,它可以处理多达 20 亿条记录,并且不需要大 int
2.change key_buffer_size(最多25%的内存)如果您的服务器有很多Myisam或只有myisam表,您可以将其增加到60-70% 尝试手动chache
SET GLOBAL keycache1.key_buffer_size=256*1024;
CACHE INDEX t1,t2 IN keycache1;
LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
(IGNORE LEAVES 修饰符只导致索引的非叶节点的块被重新加载)
3.正如您提到的,您的表增长得更快,最好对表进行分区,这将提高性能
4.执行表维护任务,例如经常分析表,更新索引,优化表并检查并修复如果有任何错误(经常优化表,因为你说的删除很多)
5.如果您不想更改引擎,请打开 delay_key_write 变量(特定于 myisam),这会使密钥在表关闭后更新
6.运行过程分析(),它会建议您最好的数据类型
7. 如果可能且仅在有用的情况下,创建全文索引以利用 myisam
8.检查您的查询缓存(将查询缓存限制设置为按需)并激活慢查询日志
9.使用表检查(并根据需要重写)所有查询
最后如果你想换引擎 将您的表存储引擎更改为 innodb 并增加 innodb_buffer_pool_size 它可能会对您有所帮助
如果表上的访问次数更多,那么最好转移到innodb,因为myisam将实现表级锁定,因为一些查询没有记录在慢查询日志中(获取锁所需的初始时间在mysql 中的执行时间)
【讨论】:
谢谢回答,这不是唯一的表,还有很多这样的表,所以我还有很多工作要做:) 您只需先优化、检查、修复、分析所有表,并确保在执行修复之前应进行备份【参考方案2】:打开MySQL Slow Query Log 以查找最慢的查询。
如果它们是选择然后通过EXPLAIN 运行它们以找出正在使用的索引(如果有的话)。您也许可以将一些索引转换为多列索引并通过这种方式找到一些改进。请参阅Multiple Indexes vs Multi-Column Indexes 以获得关于差异的良好讨论。
插入、更新和删除可能会因您的索引而变慢。您需要找出哪些索引没有被使用并删除它们。不幸的是,除了运行您最常用的查询之外,没有其他简单的方法可以做到这一点。
减小过大列的大小是个好主意。
我知道这些天使用 MyISAM 的唯一原因是在进行全文搜索时。您应该按照您的建议切换到 InnoDB。 (ALTER TABLE calculate
ENGINE = InnoDB;)
这是为了避免连接而展开的表吗?您必须在此表中有OfferteTekst
列吗?即使将其提取到相关表中也可能会有所帮助,但如果您最终只是加入反对它,则不会。
【讨论】:
以上是关于优化 mysql 架构,需要建议的主要内容,如果未能解决你的问题,请参考以下文章
从零到上亿用户,我是如何一步步优化MySQL数据库的?(建议收藏)