ITPub博客

首页 > 数据库 > > 8.6 优化 MyIASM 表

8.6 优化 MyIASM 表

作者:飘絮絮絮丶 时间:2020-05-13 10:01:54 0 删除 编辑

参考官方文档:

dev.mysql.com/doc/refma


MyISAM存储引擎在读取主要数据或低并发性操作时表现最佳,因为表锁定限制了执行同时更新的能力。 在MySQL 5.7中,InnoDB是默认的存储引擎,而不是MyISAM。



8.6.1 优化 MyISAM 查询


加快MyISAM表查询的一些常规技巧:



  • 为了帮助MySQL更好地优化查询,请使用ANALYZE TABLE或运行myisamchk --analyze 在载入数据之后对其进行分析。 这将更新每个索引部分的值,该值指示具有相同值的平均行数。 (对于唯一索引,这总是1.)当你基于非常量表达式连接两个表时,MySQL使用它来决定选择哪个索引。 您可以使用SHOW INDEX FROM tbl_name检查表分析的结果并检查基数值。 myisamchk --description --verbose显示索引分布信息。
  • 要根据索引对索引和数据进行排序,请使用myisamchk --sort-index --sort-records=1(假设您要对索引1进行排序)。 如果您有一个唯一索引,您可以根据索引按顺序读取所有行,那么这是一种更快查询的好方法。 第一次以这种方式排列大表时,可能需要很长时间。
  • 尽量避免在经常更新的MyISAM表上进行复杂的SELECT查询,以避免由于读和写之间的争用而发生表锁问题。
  • MyISAM支持并发插入:如果一个表在数据文件中间没有空闲块,那么可以在其他线程正在从表中读取的同时向其中插入新行。 如果能做到这一点很重要,请考虑以避免删除行的方式使用表。 另一种可能性是运行OPTIMIZE TABLE,在删除了很多行之后对表进行碎片整理。 这个行为是通过设置concurrent_insert变量来改变的。 您可以强制添加新行(因此允许并发插入),即使在已删除行的表中也是如此。
  • 对于频繁更改的MyISAM表,请尽量避免使用所有可变长度的列(VARCHAR,BLOB和TEXT)。 如果该表甚至包含单个可变长度列,则该表使用动态行格式。


参考Chapter 15, Alternative Storage Engines.


  • 使用ALTER TABLE ... ORDER BY expr1,expr2,...如果您通常检索expr1,expr2,... order中的行。 在对表进行大量更改后使用此选项,您可能会获得更高的性能。

--这个有点像减少聚簇因子的感觉,但是行在某一字段顺序排序之后,其他的字段可能更无序


  • 如果您经常需要根据很多行的信息来计算结果(例如计数),则最好引入一个新表并实时更新计数器。 以下表单的更新速度非常快:


UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;


当您使用仅具有表级锁定功能的MySQL存储引擎(多个读,而单个写)时,这一点非常重要。 这也为大多数数据库系统提供了更好的性能,因为在这种情况下行锁管理器不太容易。



----oracle 在这锁机制一点上不能不说确实很强大。



  • 定期使用OPTIMIZE TABLE来避免使用动态格式的MyISAM表进行分片。
  • 使用DELAY_KEY_WRITE=1表选项声明MyISAM表使索引更新速度更快,因为它们在表关闭之前不会刷新到磁盘。 缺点是,如果在这样的表打开的情况下杀死了服务器,那么必须通过运行带有--myisam-recover-options选项的服务器,或者在重新启动服务器之前运行myisamchk来确保表可以正常运行。 (但是,即使在这种情况下,使用DELAY_KEY_WRITE也不会丢失任何内容,因为key信息总是可以从数据行中生成。)
  • 字符串在MyISAM索引中自动进行前缀和后端压缩
  • 您可以通过在应用程序中缓存查询或答案,然后一起执行许多插入或更新来提高性能。 在此操作期间锁定表可确保索引缓存在所有更新后仅被刷新一次。 您还可以利用MySQL的查询缓存来获得类似的结果




8.6.2 为MyISAM 批量加载数据


这些性能提示补充了快速插入的一般准则


  • 对于MyISAM表,如果在数据文件中间没有删除的行,则可以使用并行插入在SELECT语句运行的同时添加行。
  • 通过一些额外的工作,当表有很多索引时,可以使LOAD DATA INFILE对MyISAM表运行得更快。 使用以下过程:
  1. 执行FLUSH TABLES语句或mysqladmin flush-tables命令。
  2. 使用myisamchk --keys-used = 0 -rq /path/to/db/tbl_name删除表中所有索引的使用。
  3. 用LOAD DATA INFILE将数据插入表格。 这不会更新任何索引,因此速度非常快。
  4. 如果您打算以后只从表中读取数据,请使用myisampack进行压缩
  5. 使用myisamchk -rq /path/to/db/tbl_name重新创建索引。 这会在写入磁盘之前在内存中创建索引树,这比在LOAD DATA INFILE期间更新索引快得多,因为它避免了大量的磁盘搜索。 得到的索引树也是完美平衡的。
  6. 执行FLUSH TABLES语句或mysqladmin flush-tables命令。



如果您插入数据的MyISAM表为空,则LOAD DATA INFILE会自动执行上述优化。 自动优化和明确使用过程的主要区别在于,您可以让myisamchk为索引创建分配更多的临时内存,而不是在执行LOAD DATA INFILE语句时服务器为索引重新创建分配内存。


您还可以使用以下语句而不是myisamchk来禁用或启用MyISAM表的非唯一索引。 如果您使用这些语句,则可以跳过FLUSH TABLES操作:


ALTER TABLE tbl_name DISABLE KEYS;

ALTER TABLE tbl_name ENABLE KEYS;


  • 要加快对非事务表使用多个语句执行的INSERT操作,请锁定您的表:


LOCK TABLES a WRITE;

INSERT INTO a VALUES (1,23),(2,34),(4,33);

INSERT INTO a VALUES (8,26),(6,29);

...

UNLOCK TABLES;


这有利于性能,因为在完成所有INSERT语句后,索引缓冲区只刷新一次。 通常情况下,INSERT语句将会有多个索引缓冲区刷新。 如果可以使用单个INSERT插入所有行,则不需要显式锁定语句。


锁定还会降低多连接测试的总时间,但个别连接的最长等待时间可能会因为等待锁定而增加。 假设五个客户端尝试同时执行插入操作,如下所示:


  • 连接1 做1000个插入
  • 连接2,3和4做1个插入
  • 连接5做1000个插入



如果不使用锁定,则连接2,3和4会在1和5之前完成。如果使用锁定,连接2,3和4可能在1或5之前未完成,但总时间应该约为更快40%。


INSERT,UPDATE和DELETE操作在MySQL中速度非常快,但是通过在大于五次连续插入或更新的情况下添加锁,可以获得更好的整体性能。 如果你做了很多次连续的插入操作,你可以先做一个LOCK TABLES,后跟一个UNLOCK TABLES(每行大约1000行),以允许其他线程访问表。 这仍然会带来不错的性能提升。


即使在使用刚刚列出的策略时,对于加载数据,INSERT仍然比LOAD DATA INFILE慢得多。



  • 为了提高MyISAM表的性能,对于LOAD DATA INFILE和INSERT,通过增加key_buffer_size系统变量来扩大key缓存。




8.6.3 repair table 语句的速度


用于MyISAM表的REPAIR TABLE类似于使用myisamchk进行修复操作,以及一些相同的性能优化应用:


  • myisamchk有控制内存分配的变量。
  • 对于REPAIR TABLE,同样的原则适用,但是由于修复是由服务器完成的,所以设置服务器系统变量而不是myisamchk变量。 此外,除了设置内存分配变量之外,增加myisam_max_sort_file_size系统变量还会增加修复将使用更快的文件排序方法的可能性,并避免通过键缓存方法进行更慢的修复。 在检查确定有足够的可用空间来保存表文件副本之后,将变量设置为系统的最大文件大小。 可用空间必须在包含原始表文件的文件系统中可用。





假设使用以下选项设置myisamchk表修复操作来设置其内存分配变量:

--key_buffer_size=128M --myisam_sort_buffer_size=256M

--read_buffer_size=64M --write_buffer_size=64M


其中一些myisamchk变量对应于服务器系统变量:

myisamchk Variable

System Variable

key_buffer_size

key_buffer_size

myisam_sort_buffer_size

myisam_sort_buffer_size

read_buffer_size

read_buffer_size

write_buffer_size

none



每个服务器系统变量都可以在运行时设置,其中一些(myisam_sort_buffer_size,read_buffer_size)除了具有全局值之外还具有会话值。设置会话值限制了更改对当前会话的影响,不会影响其他用户。更改全局变量(key_buffer_size,myisam_max_sort_file_size)也会影响其他用户。对于key_buffer_size,您必须考虑到缓冲区是与这些用户共享的。例如,如果将myisamchk key_buffer_size变量设置为128MB,则可以将相应的key_buffer_size系统变量设置为大于此值(如果它尚未设置得较大),以允许其他会话中的活动使用密钥缓冲区。但是,更改全局密钥缓冲区大小将使缓冲区无效,从而导致磁盘I / O增加以及其他会话减速。避免此问题的替代方法是使用单独的key缓存,为其分配要修复的表中的索引,并在修复完成时将其解除分配。


根据前面的说明,REPAIR TABLE操作可以按如下方式进行,以使用类似于myisamchk命令的设置。 这里分配了一个单独的128MBkey缓冲区,假定文件系统允许文件大小至少为100GB。

SET SESSION myisam_sort_buffer_size = 256*1024*1024;

SET SESSION read_buffer_size = 64*1024*1024;

SET GLOBAL myisam_max_sort_file_size = 100*1024*1024*1024;

SET GLOBAL repair_cache.key_buffer_size = 128*1024*1024;

CACHE INDEX tbl_name IN repair_cache;

LOAD INDEX INTO CACHE tbl_name;

REPAIR TABLE tbl_name ;

SET GLOBAL repair_cache.key_buffer_size = 0;


如果您打算更改全局变量,但只希望在REPAIR TABLE操作期间这样做,以最小化影响其他用户,请将其值保存在用户变量中,然后再恢复。 例如:

SET @old_myisam_sort_buffer_size = @@global.myisam_max_sort_file_size;

SET GLOBAL myisam_max_sort_file_size = 100*1024*1024*1024;

REPAIR TABLE tbl_name ;

SET GLOBAL myisam_max_sort_file_size = @old_myisam_max_sort_file_size;



影响REPAIR TABLE的系统变量可以在服务器启动时全局设置,如果您希望这些值在默认情况下有效。 例如,将这些行添加到服务器my.cnf文件中:

[mysqld]

myisam_sort_buffer_size=256M

key_buffer_size=1G

myisam_max_sort_file_size=100G



这些设置不包括read_buffer_size。 如果将全局read_buffer_size设置为较大值,则对于所有会话都会这样做,并且会导致性能受到多个同时会话的服务器的内存分配过多的影响。

---每个会话256M还是比较吃内存的,分析库适合。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3156670/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42290