您的位置:首页 > 博客中心 > 数据库 >

大数据量时Mysql的优化

时间:2022-03-15 10:46

(转自网络)

如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。但是,在有些场合NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。

  虽然关系型数据库在海量数据中逊色于NoSQL数据库,但是如果你操作正确,它的性能还是会满足你的需求的。针对数据的不同操作,其优化方向也是不尽相同。对于数据移植,查询和插入等操作,可以从不同的方向去考虑。而在优化的时候还需要考虑其他相关操作是否会产生影响。就比如你可以通过创建索引提高查询性能,但是这会导致插入数据的时候因为要建立更新索引导致插入性能降低,你是否可以接受这一降低那。所以,对数据库的优化是要考虑多个方向,寻找一个折衷的最佳方案。

  在这里主要分析query cache,它是主要用来缓存查询数据。当你想使用该cache,必须把query_cache_size大小设置为非0。当设置大小为非0的时候,server会就会缓存每次查询返回的结果,到下次相同查询server就直接从缓存获取数据,而不是再执行查询。能缓存的数据量就和你的size大小设置有关,所以当你设置的足够大,数据可以完全缓存到内存,速度就会非常之快。

  但是,query cache也有它的弊端。当你对数据表做任何的更新操作(update/insert/delete)等操作,server为了保证缓存与数据库的一致性,会强制刷新缓存数据,导致缓存数据全部失效。所以,当一个表格的更新数据表操作非常多的话,query cache是不会起到查询提升的性能,还会影响其他操作的性能。

  当你设置slow_query_log为on的时候,server端会对每次的查询进行记录,当超过你设置的慢查询时间 (long_query_time)的时候就把该条查询记录到日志。而你对性能进行优化的时候,就可以分析慢查询日志,对慢查询的查询语句进行有目的的优化。可以通过创建各种索引,可以通过分表等操作。那为什么要分库分表那,当不分库分表的时候那个地方是限制性能的地方啊。下面我们就简单介绍。

当我们为 group_id 字段加上索引后:

技术分享图片

我们可以看到,前一个结果显示搜索了 7883 行,而后一个只是搜索了两个表的 9 和 16 行。查看rows列可以让我们找到潜在的性能问题。

// 没有效率的: $r = mysql_query( "SELECT * FROM user WHERE country = ‘China‘" ); if (mysql_num_rows( $r ) > 0) { // ... } // 有效率的: $r = mysql_query( "SELECT 1 FROM user WHERE country = ‘China‘ LIMIT 1" ); if (mysql_num_rows( $r ) > 0) { // ... } 4. 为搜索字段建索引

索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。

技术分享图片

从上图你可以看到那个搜索字串 “last_name LIKE ‘a%’”,一个是建了索引,一个是没有索引,性能差了4倍左右。

另外,你应该也需要知道什么样的搜索是不能使用正常的索引的。例如,当你需要在一篇大的文章中搜索一个词时,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是没有意义的。你可能需要使用 或是自己做一个索引(比如说:搜索关键词或是Tag什么的)

一定要注意,这些只是建议,只有当你的表里的数据越来越多时,这些建议才会变得准确。一定要记住,你才是最终做决定的人。

1 2 3 4 5 6 7 8 9 10 while (1) {      //每次只做1000条      mysql_query( "DELETE FROM logs WHERE log_date <= ‘2009-11-01‘ LIMIT 1000" );      if (mysql_affected_rows() == 0) {          // 没得可删了,退出!          break ;      }      // 每次都要休息一会儿      usleep(50000); }

18. 越小的列会越快

对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把你的数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。

参看 MySQL 的文档  查看所有的数据类型。

如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。

当然,你也需要留够足够的扩展空间,不然,你日后来干这个事,你会死的很难看,参看 (2009年11月06日),一个简单的ALTER TABLE语句花了3个多小时,因为里面有一千六百万条数据。

19. 选择正确的存储引擎

在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。酷壳以前文章《 》讨论和这个事情。

MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都 无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。

InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

下面是MySQL的手册

20. 使用一个对象关系映射器(Object Relational Mapper)

使用 ORM (Object Relational Mapper),你能够获得可靠的性能增涨。一个ORM可以做的所有事情,也能被手动的编写出来。但是,这需要一个高级专家。

ORM 的最重要的是“Lazy Loading”,也就是说,只有在需要的去取值的时候才会去真正的去做。但你也需要小心这种机制的副作用,因为这很有可能会因为要去创建很多很多小的查 询反而会降低性能。

ORM 还可以把你的SQL语句打包成一个事务,这会比单独执行他们快得多得多。

目前,个人最喜欢的PHP的ORM是: 。

21. 小心“永久链接”

“永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了,它会永远处在连接的状态,就算是数据库操作已经结束了。而且,自 从我们的Apache开始重用它的子进程后——也就是说,下一次的HTTP请求会重用Apache的子进程,并重用相同的 MySQL 链接。

在理论上来说,这听起来非常的不错。但是从个人经验(也是大多数人的)上来说,这个功能制造出来的麻烦事更多。因为,你只有有限的链接数,内存问 题,文件句柄数,等等。

而且,Apache 运行在极端并行的环境中,会创建很多很多的了进程。这就是为什么这种“永久链接”的机制工作地不好的原因。在你决定要使用“永久链接”之前,你需要好好地 考虑一下你的整个系统的架构。

本类排行

今日推荐

热门手游