1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中使用!=或操作符,否则将引擎放弃使用索引而进行全表扫描。
3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.下面的查询也将导致全表扫描:
select id from t where name like '%abc%'
若要提高效率,可以考虑全文检索。
6.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0--'2005-11-30'生成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate
MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。例如,在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任务了。同样的,如果可以的话,我们应该使用MEDIUMINT而不是 BIGIN来定义整型字段。
另外一个提高效率的方法是在可能的情况下,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。
对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。
1.存储引擎的选择如果数据表需要事务处理,应该考虑使用InnoDB,因为它完全符合ACID特性。如果不需要事务处理,使用默认存储引擎MyISAM是比较明智的。并且不要尝试同时使用这两个存储引擎。思考一下:在一个事务处理中,一些数据表使用InnoDB,而其余的使用MyISAM.结果呢?整个subject将被取消,只有那些在事务处理中的被带回到原始状态,其余的被提交的数据转存,这将导致整个数据库的冲突。然而存在一个简单的方法可以同时利用两个存储引擎的优势。目前大多数MySQL套件中包括InnoDB、编译器和链表,但如果你选择MyISAM,你仍然可以单独下载InnoDB,并把它作为一个插件。很简单的方法,不是吗?
2.计数问题如果数据表采用的存储引擎支持事务处理(如InnoDB),你就不应使用COUNT(*)计算数据表中的行数。这是因为在产品类数据库使用COUNT(*),最多返回一个近似值,因为在某个特定时间,总有一些事务处理正在运行。如果使用COUNT(*)显然会产生bug,出现这种错误结果。
3.反复测试查询查询最棘手的问题并不是无论怎样小心总会出现错误,并导致bug出现。恰恰相反,问题是在大多数情况下bug出现时,应用程序或数据库已经上线。的确不存在针对该问题切实可行的解决方法,除非将测试样本在应用程序或数据库上运行。任何数据库查询只有经过上千个记录的大量样本测试,才能被认可。
4.避免全表扫描通常情况下,如果MySQL(或者其他关系数据库模型)需要在数据表中搜索或扫描任意特定记录时,就会用到全表扫描。此外,通常最简单的方法是使用索引表,以解决全表扫描引起的低效能问题。然而,正如我们在随后的问题中看到的,这存在错误部分。
5.使用“EXPLAIN”进行查询当需要调试时,EXPLAIN是一个很好的命令,下面将对EXPLAIN进行深入探讨。
mysql的优化大的有两方面:1、配置优化 配置的优化其实包含两个方面的:操作系统内核的优化和mysql配置文件的优化 1)系统内核的优化对专用的mysql服务器来说,无非是内存实用、连接数、超时处理、TCP处理等方面的优化,根据自己的硬件配置来进行优化,这里不多讲; 2)mysql配置的优化,一般来说包含:IO处理的常用参数、最大连接数设置、缓存使用参数的设置、慢日志的参数的设置、innodb相关参数的设置等,如果有主从关系在设置主从同步的相关参数即可,网上的相关配置文件很多,大同小异,常用的设置大多修改这些差不多就够用了。
2、sql语句的优化1、尽量稍作计算 Mysql的作用是用来存取数据的,不是做计算的,做计算的话可以用其他方法去实现,mysql做计算是很耗资源的。2.尽量少 join MySQL 的优势在于简单,但这在某些方面其实也是其劣势。
MySQL 优化器效率高,但是由于其统计信息的量有限,优化器工作过程出现偏差的可能性也就更多。对于复杂的多表 Join,一方面由于其优化器受限,再者在 Join 这方面所下的功夫还不够,所以性能表现离 Oracle 等关系型数据库前辈还是有一定距离。
但如果是简单的单表查询,这一差距就会极小甚至在有些场景下要优于这些数据库前辈。3.尽量少排序 排序操作会消耗较多的 CPU 资源,所以减少排序可以在缓存命中率高等 IO 能力足够的场景下会较大影响 SQL的响应时间。
对于MySQL来说,减少排序有多种办法,比如: 通过利用索引来排序的方式进行优化 减少参与排序的记录条数 非必要不对数据进行排序4.尽量避免 select * 在数据量少并且访问量不大的情况下,select * 没有什么影响,但是量级达到一定级别的时候,在执行效率和IO资源的使用上,还是有很大关系的,用什么字段取什么字段,减少不必要的资源浪费。 之前遇到过因为一个字段存储的数据比较大,并发高的情况下把网络带宽跑满的情况,造成网站打不开或是打开速度极慢的情况。
5.尽量用 join 代替子查询 虽然 Join 性能并不佳,但是和 MySQL 的子查询比起来还是有非常大的性能优势。MySQL 的子查询执行计划一直存在较大的问题,虽然这个问题已经存在多年,但是到目前已经发布的所有稳定版本中都普遍存在,一直没有太大改善。
虽然官方也在很早就承认这一问题,并且承诺尽快解决,但是至少到目前为止我们还没有看到哪一个版本较好的解决了这一问题。6.尽量少 or 当 where 子句中存在多个条件以“或”并存的时候,MySQL 的优化器并没有很好的解决其执行计划优化问题,再加上 MySQL 特有的 SQL 与 Storage 分层架构方式,造成了其性能比较低下,很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果。
7.尽量用 union all 代替 union union 和 union all 的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的 CPU 运算,加大资源消耗及延迟。所以当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用 union all 而不是 union。
8.尽量早过滤 这一优化策略其实最常见于索引的优化设计中(将过滤性更好的字段放得更靠前)。 在 SQL 编写中同样可以使用这一原则来优化一些 Join 的 SQL。
比如我们在多个表进行分页数据查询的时候,我们最好是能够在一个表上先过滤好数据分好页,然后再用分好页的结果集与另外的表 Join,这样可以尽可能多的减少不必要的 IO 操作,大大节省 IO 操作所消耗的时间。9.避免类型转换 这里所说的“类型转换”是指 where 子句中出现 column 字段的类型和传入的参数类型不一致的时候发生的类型转换:A:人为在column_name 上通过转换函数进行转换 直接导致 MySQL(实际上其他数据库也会有同样的问题)无法使用索引,如果非要转换,应该在传入的参数上进行转换 B:由数据库自己进行转换 如果我们传入的数据类型和字段类型不一致,同时我们又没有做任何类型转换处理,MySQL 可能会自己对我们的数据进行类型转换操作,也可能不进行处理而交由存储引擎去处理,这样一来,就会出现索引无法使用的情况而造成执行计划问题。
以上两种情况在开发者因为某种原因经常会有,本来可以用到索引的结果类型不对没有用到索引,或是因为类型不对又有越界的情况发生造成无法使用索引的情况,结果造成很严重的事故。10.优先优化高并发的 SQL,而不是执行频率低某些“大”SQL 对于破坏性来说,高并发的 SQL 总是会比低频率的来得大,因为高并发的 SQL 一旦出现问题,甚至不会给我们任何喘息的机会就会将系统压跨。
而对于一些虽然需要消耗大量 IO 而且响应很慢的 SQL,由于频率低,即使遇到,最多就是让整个系统响应慢一点,但至少可能撑一会儿,让我们有缓冲的机会。11.从全局出发优化,而不是片面调整 SQL 优化不能是单独针对某一个进行,而应充分考虑系统中所有的 SQL,尤其是在通过调整索引优化 SQL 的执行计划的时候,千万不能顾此失彼,因小失大。
12.尽可能对每一条运行在数据库中的SQL进行 explain 优化 SQL,需要做到心中有数,知道。
下面我们要四种关于mysql教程数据表几种有效优化方法
哦,从而提高mysql数据库教程在应用方面的数据吞吐能力。
一、优化表的数据类型
select * from tablename procedure analyse();
select * from tablename procedure analyse(16.265);
上面输出一列信息,牟你数据表的字段提出优化建义,
二、通过拆分表提高数据访问效率
拆分一是指针对表进行拆分,如果是针对myisam类型的表进行处理的话,可以有两种拆分方法
1、是垂直拆分,把主要的与一些散放到一个表,然后把主要的和另外的列放在另一张表。
2、水平拆分方法,根据一列或多列的值把数据行放到两个独立的表中,水平拆分通常几种情况。
表很大,拆分后可降低查询时数据和索引的查询速度,同时也降低了索引的层数,提高查询的速度。
表中的数据本来就有独立性,表中分别记录各个地区的数据或不同时期的数据,特别是有些数据常用,厕国一些数据不常用的情况下,
需要把数据存放到多个不同的介质上。
三、逆规范化
四、使用中间表优化方法对于数据库教程大的表,在进行统计查询时通常会比较慢的,并且还要考虑查询是否会对在线应用产生影响,通常这种情况下我们使用中间表可以提高查询统计速度
(1).选取最适用的字段属性,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。
(2).使用连接(JOIN)来代替子查询(Sub-Queries)
(3).使用联合(UNION)来代替手动创建的临时表
(4).尽量少使用 LIKE 关键字和通配符
(5).使用事务和外键
或者
(1).数据库设计方面,这是DBA和Architect的责任,设计结构良好的数据库,必要的时候,去正规化(英文是这个:denormalize,中文翻译成啥我不知道),允许部分数据冗余,避免JOIN操作,以提高查询效率
(2).系统架构设计方面,表散列,把海量数据散列到几个不同的表里面.快慢表,快表只留最新数据,慢表是历史存档.集群,主服务器Read & write,从服务器read only,或者N台服务器,各机器互为Master
(3).(1)和(2)超越PHP Programmer的要求了,会更好,不会没关系.检查有没有少加索引
(4).写高效的SQL语句,看看有没有写低效的SQL语句,比如生成笛卡尔积的全连接啊,大量的Group By和order by,没有limit等等.必要的时候,把数据库逻辑封装到DBMS端的存储过程里面.缓存查询结果,explain每一个sql语句
(5).所得皆必须,只从数据库取必需的数据,比如查询某篇文章的评论数,select count(*) 。 where article_id = 就可以了,不要先select * 。 where article_id = 然后msql_num_rows.只传送必须的SQL语句,比如修改文章的时候,如果用户只修改了标题,那就update 。 set title = where article_id = 不要set content = (大文本)
(6).必要的时候用不同的存储引擎.比如InnoDB可以减少死锁.HEAP可以提高一个数量级的查询速度
1) 数据库设计方面设计结构良好的数据库,必要的时候,去正规化允许部分数据冗余,避免 JOIN 操作,以提高查询效率2) 系统架构设计方面,表散列,把海量数据散列到几个不同的表里面。
快慢表,快表只留最新数据,慢表是历史存档。集群,主服务器进行读写,从服务器只读,或者 N 台服务器,各机器互为 Master3) 检查有没有少加索引4) 写高效的 SQL 语句,减少低效的 SQL 语句,比如生成笛卡尔积的全连接,大量的 Group By 和 order by,limit 等等。
必要的时候,把数据库逻辑封装到 DBMS 端的存储过程里面。缓存查询结果,explain 每一个 sql语句5) 必要的时候用不同的存储引擎。
比如 InnoDB 可以减少死锁, HEAP 可以提高一个数量级的查询速度。
优化方案:
主从同步+读写分离:
这个表在有设备条件的情况下,读写分离,这样能减少很多压力,而且数据稳定性也能提高
纵向分表:
根据原则,每个表最多不要超过5个索引,纵向拆分字段,将部分字段拆到一个新表
通常我们按以下原则进行垂直拆分:(先区分这个表中的冷热数据字段)
把不常用的字段单独放在一张表;
把text,blob等大字段拆分出来放在附表中;
经常组合查询的列放在一张表中;
缺点是:很多逻辑需要重写,带来很大的工作量。
利用表分区:
这个是推荐的一个解决方案,不会带来重写逻辑等,可以根据时间来进行表分区,相当于在同一个磁盘上,表的数据存在不同的文件夹内,能够极大的提高查询速度。
横向分表:
1000W条数据不少的,会带来一些运维压力,备份的时候,单表备份所需时间会很长,所以可以根据服务器硬件条件进行水平分表,每个表有多少数据为准。
#1: 使用索引 MySQL允许对数据库表进行索引,以此能迅速查找记录,而无需一开始就扫描整个表,由此显著地加快查询速度。
每个表最多可以做到16个索引,此外MySQL还支持多列索引及全文检索。 给表添加一个索引非常简单,只需调用一个CREATE INDEX命令并为索引指定它的域即可。
列表A给出了一个例子:列表 Amysql> CREATE INDEX idx_username ON users(username);Query OK, 1 row affected (0。15 sec)Records: 1 Duplicates: 0 Warnings: 0 这里,对users表的username域做索引,以确保在WHERE或者HAVING子句中引用这一域的SELECT查询语句运行速度比没有添加索引时要快。
通过SHOW INDEX命令可以查看索引已被创建(列表B)。列表 Bmysql> SHOW INDEX FROM users;--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| users | 1 | idx_username | 1 | username | A | NULL | NULL | NULL | YES | BTREE | |--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+1 row in set (0。
00 sec) 值得注意的是:索引就像一把双刃剑。对表的每一域做索引通常没有必要,且很可能导致运行速度减慢,因为向表中插入或修改数据时,MySQL不得不每次都为这些额外的工作重新建立索引。
另一方面,避免对表的每一域做索引同样不是一个非常好的主意,因为在提高插入记录的速度时,导致查询操作的速度减慢。 这就需要找到一个平衡点,比如在设计索引系统时,考虑表的主要功能(数据修复及编辑)不失为一种明智的选择。
#2: 优化查询性能 在分析查询性能时,考虑EXPLAIN关键字同样很管用。EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作、以及MySQL成功返回结果集需要执行的行数。
下面的一个简单例子可以说明(列表C)这一过程:列表 Cmysql> EXPLAIN SELECT city。name, city。
district FROM city, country WHERE city。countrycode = country。
code AND country。code = 'IND';+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index || 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4079 | Using where |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+2 rows in set (0。
00 sec)这里查询是基于两个表连接。EXPLAIN关键字描述了MySQL是如何处理连接这两个表。
必须清楚的是,当前设计要求MySQL处理的是country表中的一条记录以及city表中的整个4019条记录。这就意味着,还可使用其他的优化技巧改进其查询方法。
例如,给city表添加如下索引(列表D):列表 Dmysql> CREATE INDEX idx_ccode ON city(countrycode);Query OK, 4079 rows affected (0。15 sec)Records: 4079 Duplicates: 0 Warnings: 0现在,当我们重新使用EXPLAIN关键字进行查询时,我们可以看到一个显著的改进(列表E):列表 Emysql> EXPLAIN SELECT city。
name, city。district FROM city, country WHERE city。
countrycode = country。code AND country。
code = 'IND';+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+| 1 | SIMPLE | country | const | PRIMARY | PRIMARY | 3 | const | 1 | Using index || 1 | SIMPLE | city | ref | idx_ccode | idx_ccode | 3 | const | 333 | Using where |+----+-------------+---------+-------+---------------+-----------+---------+-------+------+-------------+2 rows in set (0。 01 sec) 在这个例子中,MySQL现在只需要扫描city表中的333条记录就可产生一个结果集,其扫描记录数几乎减少了90%!自然,数据库资源的查询速度更快,效率更高。
#3: 调整内部变量 MySQL是如此的开放,所以可轻松地进一步调整其缺省设置以获得更优的性能及稳定性。 需要优化的一些关键变量如下:改变索引缓冲区长度(key_buffer) 一般,该变量控制缓冲区的长度在处理索引表(读/写操作)时使用。
MySQL使用手册指出该变量可以不断增加以确保索引表的最佳性能,并推荐使用与系统内存25%的大小作为该变量的值。 这是MySQL十分重要的配置变量之一,如果你对优化和提高系统性能有兴趣,可以从改变key_buffer_size变量的值开始。
改变表长(read_buffer_size) 当一个查询不断地扫描某一个表,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。
如果你认为连续扫描进行得太慢,可以。
声明:本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
蜀ICP备2020033479号-4 Copyright © 2016 学习鸟. 页面生成时间:3.701秒