mysql优化

一.mysql配置优化
1、修改MySQL配置
打开MySQL配置文件my.cnf

vi /etc/my.cnf

1.1 MySQL非缓存参数变量介绍及修改

修改back_log参数值:由默认的50修改为500.(每个连接256kb,占用:125M)
back_log=500
back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果MySql的连接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。将会报:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时.
back_log值不能超过TCP/IP连接的侦听队列的大小。若超过则无效,查看当前系统的TCP/IP连接的侦听队列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系统为1024。对于Linux系统推荐设置为小于512的整数。
修改系统内核参数,)http://www.51testing.com/html/64/n-810764.html
查看mysql 当前系统默认back_log值,命令:
show variables like 'back_log'; 查看当前数量

1.2修改wait_timeout参数值,由默认的8小时,修改为30分钟。(本次不用)
wait_timeout=1800(单位为妙)

我对wait-timeout这个参数的理解:MySQL客户端的数据库连接闲置最大时间值。
说得比较通俗一点,就是当你的MySQL连接闲置超过一定时间后将会被强行关闭。MySQL默认的wait-timeout 值为8个小时,可以通过命令show variables like ‘wait_timeout’查看结果值;。
设置这个值是非常有意义的,比如你的网站有大量的MySQL链接请求(每个MySQL连接都是要内存资源开销的 ),由于你的程序的原因有大量的连接请求空闲啥事也不干,白白占用内存资源,或者导致MySQL超过最大连接数从来无法新建连接导致“Too many connections”的错误。在设置之前你可以查看一下你的MYSQL的状态(可用show processlist),如果经常发现MYSQL中有大量的Sleep进程,则需要 修改wait-timeout值了。
interactive_timeout:服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。
wait_timeout:服务器关闭非交互连接之前等待活动的秒数。在线程启动时,根据全局wait_timeout值或全局 interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义).
这两个参数必须配合使用。否则单独设置wait_timeout无效

1.3修改max_connections参数值,由默认的151,修改为3000(750M)。
max_connections=3000
max_connections是指MySql的最大连接数,如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量,当然这建立在机器能支撑的情况下,因为如果连接数越多,介于MySql会为每个连接提供连接缓冲区,就会开销越多的内存,所以要适当调整该值,不能盲目提高设值。可以过’conn%’通配符查看当前状态的连接数量,以定夺该值的大小。
MySQL服务器允许的最大连接数16384;
查看系统当前最大连接数:
show variables like ‘max_connections’;

1.4修改max_user_connections值,由默认的0,修改为800
max_user_connections=800
max_user_connections是指每个数据库用户的最大连接
针对某一个账号的所有客户端并行连接到MYSQL服务的最大并行连接数。简单说是指同一个账号能够同时连接到mysql服务的最大连接数。设置为0表示不限制。
目前默认值为:0不受限制。
这儿顺便介绍下Max_used_connections:它是指从这次mysql服务启动到现在,同一时刻并行连接数的最大值。它不是指当前的连接情况,而是一个比较值。如果在过去某一个时刻,MYSQL服务同时有1000个请求连接过来,而之后再也没有出现这么大的并发请求时,则Max_used_connections=1000.请注意与show variables 里的max_user_connections的区别。默认为0表示无限大。
查看max_user_connections值
show variables like ‘max_user_connections’;

1.5修改thread_concurrency值,由目前默认的8,修改为64
thread_concurrency=64
thread_concurrency的值的正确与否, 对mysql的性能影响很大, 在多个cpu(或多核)的情况下,错误设置了thread_concurrency的值, 会导致mysql不能充分利用多cpu(或多核), 出现同一时刻只能一个cpu(或核)在工作的情况。
thread_concurrency应设为CPU核数的2倍. 比如有一个双核的CPU, 那thread_concurrency 的应该为4; 2个双核的cpu, thread_concurrency的值应为8.
比如:根据上面介绍我们目前系统的配置,可知道为4个CPU,每个CPU为8核,按照上面的计算规则,这儿应为:4*8*2=64
查看系统当前thread_concurrency默认配置命令:
show variables like ‘thread_concurrency’;

1.6添加skip-name-resolve,默认被注释掉,没有该参数。
skip-name-resolve
skip-name-resolve:禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!
1.7 skip-networking,默认被注释掉。没有该参数。(本次无用)
skip-networking建议被注释掉,不要开启
开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!否则将无法正常连接!
1.8 default-storage-engine(设置MySQL的默认存储引擎)
default-storage-engine= InnoDB(设置InnoDB类型,另外还可以设置MyISAM类型)
设置创建数据库及表默认存储类型
show table status like ‘tablename’显示表的当前存储状态值
查看MySQL有哪些存储状态及默认存储状态
show engines;
创建表并指定存储类型
CREATE TABLE mytable (id int, title char(20)) ENGINE = INNODB;
修改表存储类型:
Alter table tableName engine =engineName

备注:设置完后把以下几个开启:

Uncomment the following if you are using InnoDB tables

innodb_data_home_dir = /var/lib/mysql

innodb_data_file_path = ibdata1:1024M;ibdata2:10M:autoextend(要注释掉,否则会创建一个新的把原来的替换的。)

innodb_log_group_home_dir = /var/lib/mysql

You can set .._buffer_pool_size up to 50 - 80 %
of RAM but beware of setting memory usage too high

innodb_buffer_pool_size = 1000M
innodb_additional_mem_pool_size = 20M

Set .._log_file_size to 25 % of buffer pool size

innodb_log_file_size = 500M
innodb_log_buffer_size = 20M
innodb_flush_log_at_trx_commit = 0
innodb_lock_wait_timeout = 50
设置完后一定记得把MySQL安装目录地址(我们目前是默认安装所以地址/var/lib/mysql/)下的ib_logfile0和ib_logfile1删除掉。否则重启MySQL起动失败。

2 MySQL缓存变量介绍及修改
数据库属于IO密集型的应用程序,其主职责就是数据的管理及存储工作。而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个 IO是在毫秒级别,二者相差3个数量级。所以,要优化数据库,首先第一步需要优化的就是IO,尽可能将磁盘IO转化为内存IO。本文先从MySQL数据库 IO相关参数(缓存参数)的角度来看看可以通过哪些参数进行IO优化

2.1全局缓存
启动MySQL时就要分配并且总是存在的全局缓存。目前有:key_buffer_size(默认值:402653184,即384M)、innodb_buffer_pool_size(默认值:134217728即:128M)、innodb_additional_mem_pool_size(默认值:8388608即:8M)、innodb_log_buffer_size(默认值:8388608即:8M)、query_cache_size(默认值:33554432即:32M)等五个。总共:560M.
这些变量值都可以通过命令如:show variables like ‘变量名’;查看到。

2.1.1:key_buffer_size,本系统目前为384M,可修改为400M
key_buffer_size=400M
key_buffer_size是用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),对MyISAM(MySQL表存储的一种类型,可以百度等查看详情)表性能影响最大的一个参数。如果你使它太大,系统将开始换页并且真的变慢了。严格说是它决定了数据库索引处理的速度,尤其是索引读的速度。对于内存在4GB左右的服务器该参数可设置为256M或384M.
怎么才能知道key_buffer_size的设置是否合理呢,一般可以检查状态值Key_read_requests和Key_reads ,比例key_reads / key_read_requests应该尽可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like ‘key_read%’;
比如查看系统当前key_read和key_read_request值为:
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Key_read_requests | 28535 |
| Key_reads | 269 |
+——————-+——-+
可知道有28535个请求,有269个请求在内存中没有找到直接从硬盘读取索引.
未命中缓存的概率为:0.94%=269/28535*100%. 一般未命中概率在0.1之下比较好。目前已远远大于0.1,证明效果不好。若命中率在0.01以下,则建议适当的修改key_buffer_size值。
http://dbahacker.com/mysql/innodb-myisam-compare(InnoDB与MyISAM的六大区别)
http://kb.cnblogs.com/page/99810/(查看存储引擎介绍)
MyISAM、InnoDB、MyISAM Merge引擎、InnoDB、memory(heap)、archive

2.1.2:innodb_buffer_pool_size(默认128M)
innodb_buffer_pool_size=1024M(1G)
innodb_buffer_pool_size:主要针对InnoDB表性能影响最大的一个参数。功能与Key_buffer_size一样。InnoDB占用的内存,除innodb_buffer_pool_size用于存储页面缓存数据外,另外正常情况下还有大约8%的开销,主要用在每个缓存页帧的描述、adaptive hash等数据结构,如果不是安全关闭,启动时还要恢复的话,还要另开大约12%的内存用于恢复,两者相加就有差不多21%的开销。假设:12G的innodb_buffer_pool_size,最多的时候InnoDB就可能占用到14.5G的内存。若系统只有16G,而且只运行MySQL,且MySQL只用InnoDB,
那么为MySQL开12G,是最大限度地利用内存了。
另外InnoDB和 MyISAM 存储引擎不同, MyISAM 的 key_buffer_size 只能缓存索引键,而 innodb_buffer_pool_size 却可以缓存数据块和索引键。适当的增加这个参数的大小,可以有效的减少 InnoDB 类型的表的磁盘 I/O 。
当我们操作一个 InnoDB 表的时候,返回的所有数据或者去数据过程中用到的任何一个索引块,都会在这个内存区域中走一遭。
可以通过 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 计算缓存命中率,并根据命中率来调整 innodb_buffer_pool_size 参数大小进行优化。值可以用以下命令查得:show status like ‘Innodb_buffer_pool_read%’;
比如查看当前系统中系统中
| Innodb_buffer_pool_read_requests | 1283826 |
| Innodb_buffer_pool_reads | 519 |
+—————————————+———+
其命中率99.959%=(1283826-519)/1283826*100% 命中率越高越好。

2.1.3:innodb_additional_mem_pool_size(默认8M)
innodb_additional_mem_pool_size=20M
innodb_additional_mem_pool_size 设置了InnoDB存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,所以当我们一个MySQL Instance中的数据库对象非常多的时候,是需要适当调整该参数的大小以确保所有数据都能存放在内存中提高访问效率的。
这个参数大小是否足够还是比较容易知道的,因为当过小的时候,MySQL会记录Warning信息到数据库的error log中,这时候你就知道该调整这个参数大小了。
查看当前系统mysql的error日志 cat /var/lib/mysql/机器名.error 发现有很多waring警告。所以要调大为20M.
根据MySQL手册,对于2G内存的机器,推荐值是20M。
32G内存的 100M

2.1.4:innodb_log_buffer_size(默认8M)
innodb_log_buffer_size=20M
innodb_log_buffer_size 这是InnoDB存储引擎的事务日志所使用的缓冲区。类似于Binlog Buffer,InnoDB在写事务日志的时候,为了提高性能,也是先将信息写入Innofb Log Buffer中,当满足innodb_flush_log_trx_commit参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件 (或者同步到磁盘)中。可以通过innodb_log_buffer_size 参数设置其可以使用的最大内存空间。
InnoDB 将日志写入日志磁盘文件前的缓冲大小。理想值为 1M 至 8M。大的日志缓冲允许事务运行时不需要将日志保存入磁盘而只到事务被提交(commit)。 因此,如果有大的事务处理,设置大的日志缓冲可以减少磁盘I/O。 在 my.cnf中以数字格式设置。
默认是8MB,系的如频繁的系统可适当增大至4MB~8MB。当然如上面介绍所说,这个参数实际上还和另外的flush参数相关。一般来说不建议超过32MB
注:innodb_flush_log_trx_commit参数对InnoDB Log的写入性能有非常关键的影响,默认值为1。该参数可以设置为0,1,2,解释如下:
0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;
1:在每次事务提交的时候将log buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;
2:事务提交会触发log buffer到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。
实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。根据MySQL手册,在存在丢失最近部分事务的危险的前提下,可以把该值设为0。

1.5:query_cache_size(默认32M)
query_cache_size=40M
query_cache_size: 主要用来缓存MySQL中的ResultSet,也就是一条SQL语句执行的结果集,所以仅仅只能针对select语句。当我们打开了 Query Cache功能,MySQL在接受到一条select语句的请求后,如果该语句满足Query Cache的要求(未显式说明不允许使用Query Cache,或者已经显式申明需要使用Query Cache),MySQL会直接根据预先设定好的HASH算法将接受到的select语句以字符串方式进行hash,然后到Query Cache中直接查找是否已经缓存。也就是说,如果已经在缓存中,该select请求就会直接将数据返回,从而省略了后面所有的步骤(如SQL语句的解析,优化器优化以及向存储引擎请求数据等),极大的提高性能。根据MySQL用户手册,使用查询缓冲最多可以达到238%的效率。
当然,Query Cache也有一个致命的缺陷,那就是当某个表的数据有任何任何变化,都会导致所有引用了该表的select语句在Query Cache中的缓存数据失效。所以,当我们的数据变化非常频繁的情况下,使用Query Cache可能会得不偿失
Query Cache的使用需要多个参数配合,其中最为关键的是query_cache_size和query_cache_type,前者设置用于缓存 ResultSet的内存大小,后者设置在何场景下使用Query Cache。在以往的经验来看,如果不是用来缓存基本不变的数据的MySQL数据库,query_cache_size一般256MB是一个比较合适的大小。当然,这可以通过计算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))来进行调整。 query_cache_type可以设置为0(OFF),1(ON)或者2(DEMOND),分别表示完全不使用query cache,除显式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有显示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲. 如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;
根据命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))进行调整,一般不建议太大,256MB可能已经差不多了,大型的配置型静态数据可适当调大.
可以通过命令:show status like ‘Qcache_%’;查看目前系统Query catch使用大小
| Qcache_hits | 1892463 |
| Qcache_inserts | 35627
命中率98.17%=1892463/(1892463 +35627 )*100

2.2局部缓存
除了全局缓冲,MySql还会为每个连接发放连接缓冲。个连接到MySQL服务器的线程都需要有自己的缓冲。大概需要立刻分配256K,甚至在线程空闲时,它们使用默认的线程堆栈,网络缓存等。事务开始之后,则需要增加更多的空间。运行较小的查询可能仅给指定的线程增加少量的内存消耗,然而如果对数据表做复杂的操作例如扫描、排序或者需要临时表,则需分配大约read_buffer_size,
sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的内存空间. 不过它们只是在需要的时候才分配,并且在那些操作做完之后就释放了。有的是立刻分配成单独的组块。tmp_table_size 可能高达MySQL所能分配给这个操作的最大内存空间了
。注意,这里需要考虑的不只有一点——可能会分配多个同一种类型的缓存,例如用来处理子查询。一些特殊的查询的内存使用量可能更大——如果在MyISAM表上做成批的插入
时需要分配 bulk_insert_buffer_size 大小的内存;执行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令时需要分配 myisam_sort_buffer_size 大小的内存。
2.1:read_buffer_size(默认值:2097144即2M)
read_buffer_size=4M
read_buffer_size 是MySql读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。read_buffer_size变量控制这一
缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能.

2.2:sort_buffer_size(默认值:2097144即2M)
sort_buffer_size=4M
sort_buffer_size是MySql执行排序使用的缓冲大小。如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能,可以尝试增加sort_buffer_size变量的大小
2.3: read_rnd_buffer_size(默认值:8388608即8M)
read_rnd_buffer_size=8M
read_rnd_buffer_size 是MySql的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开
销过大。
2.4: tmp_table_size(默认值:8388608 即:16M)
tmp_table_size=16M
tmp_table_size是MySql的heap (堆积)表缓冲大小。所有联合在一个DML指令内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内
存的(HEAP)表。具有大的记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自
动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置tmp_table_size选项来增加临时表的大小。也就是说,如果调高该值,MySql同时将增加heap表的大小,可达到提高
联接查询速度的效果。
2.5:record_buffer:(默认值:)
record_buffer每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是131072
(128K)
3其它缓存:
3.1:table_cache(默认值:512)

TABLE_CACHE(5.1.3及以后版本又名TABLE_OPEN_CACHE)
table_cache指定表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE ‘Open%tables’获得)。注意,不能盲目地把table_cache设置成很大的值。如果设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败。
SHOW STATUS LIKE ‘Open%tables’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| Open_tables | 356 |
| Opened_tables | 0 |
+—————+——-+
2 rows in set (0.00 sec)
open_tables表示当前打开的表缓存数,如果执行flush tables操作,则此系统会关闭一些当前没有使用的表缓存而使得此状态值减小;
opend_tables表示曾经打开的表缓存数,会一直进行累加,如果执行flush tables操作,值不会减小。
在mysql默认安装情况下,table_cache的值在2G内存以下的机器中的值默认时256到512,如果机器有4G内存,则默认这个值 是2048,但这决意味着机器内存越大,这个值应该越大,因为table_cache加大后,使得mysql对SQL响应的速度更快了,不可避免的会产生 更多的死锁(dead lock),这样反而使得数据库整个一套操作慢了下来,严重影响性能。所以平时维护中还是要根据库的实际情况去作出判断,找到最适合你维护的库的 table_cache值。
由于MySQL是多线程的机制,为了提高性能,每个线程都是独自打开自己需要的表的文件描 述符,而不是通过共享已经打开的.针对不同存储引擎处理的方法当然也不一样
在myisam表引擎中,数据文件的描述符 (descriptor)是不共享的,但是索引文件的描述符却是所有线程共享的.Innodb中和使用表空间类型有关,假如是共享表空间那么实际就一个数 据文件,当然占用的数据文件描述符就会比独立表空间少.
mysql手册上给的建议大小 是:table_cache=max_connections*n
n表示查询语句中最大表数, 还需要为临时表和文件保留一些额外的文件描述符。
这个数据遭到很多质疑,table_cache够用就好,检查 Opened_tables值,如果这个值很大,或增长很快那么你就得考虑加大table_cache了.
table_cache:所有线程打开的表的数目。增大该值可以增加mysqld需要的文件描述符的数量。默认值是64.

2.3.2 thread_cache_size (服务器线程缓存)
thread_cache_size=64
默认的thread_cache_size=8,但是看到好多配置的样例里的值一般是32,64,甚至是128,感觉这个参数对优化应该有帮助,于是查了下:
根据调查发现以上服务器线程缓存thread_cache_size没有进行设置,或者设置过小,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能.通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。(–>表示要调整的值) 根据物理内存设置规则如下:
1G —> 8
2G —> 16
3G —> 32 >3G —> 64
mysql> show status like ‘thread%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 | <—当前被缓存的空闲线程的数量
| Threads_connected | 1 | <—正在使用(处于连接状态)的线程
| Threads_created | 1498 | <—服务启动以来,创建了多少个线程
| Threads_running | 1 | <—正在忙的线程(正在查询数据,传输数据等等操作)
+——————-+——-+
查看开机起来数据库被连接了多少次?
mysql> show status like ‘%connection%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Connections | 1504 | –>服务启动以来,历史连接数
| Max_used_connections | 2 |
+———————-+——-+
通过连接线程池的命中率来判断设置值是否合适?命中率超过90%以上,设定合理。
(Connections - Threads_created) / Connections * 100 %

二. SQL语句优化
30种mysql优化sql语句查询的方法
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<’2005-12-1’
  10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
  11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
  12.不要写一些没有意义的查询,如需要生成一个空表结构:
  select col1,col2 into #t from t where 1=0
  这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
  create table #t(…)

  13.很多时候用 exists 代替 in 是一个好的选择:
  select num from a where num in(select num from b)
  用下面的语句替换:
  select num from a where exists(select 1 from b where num=a.num)
  14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
  15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
  16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
  17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
  18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
  19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
  20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
  21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
  22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
  23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
  24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
  25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
  26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
  27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
  28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
  29.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
  30.尽量避免大事务操作,提高系统并发能力。

上面有几句写的有问题。

第二方面:
select Count (*)和Select Count(1)以及Select Count(column)区别
一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的
假如表沒有主键(Primary key), 那么count(1)比count(*)快,
如果有主键的話,那主键作为count的条件时候count(主键)最快
如果你的表只有一个字段的话那count(*)就是最快的
count(*) 跟 count(1) 的结果一样,都包括对NULL的统计,而count(column) 是不包括NULL的统计

第三方面:
索引列上计算引起的索引失效及优化措施以及注意事项

创建索引、优化查询以便达到更好的查询优化效果。但实际上,MySQL有时并不按我们设计的那样执行查询。MySQL是根据统计信息来生成执行计划的,这就涉及索引及索引的刷选率,表数据量,还有一些额外的因素。
Each table index is queried, and the best index is used unless the optimizer believes that it is more efficient to use a table scan. At one time, a scan
was used based on whether the best index spanned more than 30% of the table, but a fixed percentage no longer determines the choice between using an index or a scan. The optimizer now is more complex and bases its estimate on additional factors such as table
size, number of rows, and I/O block size.
简而言之,当MYSQL认为符合条件的记录在30%以上,它就不会再使用索引,因为mysql认为走索引的代价比不用索引代价大,所以优化器选择了自己认为代价最小的方式。事实也的确如此

是MYSQL认为记录是30%以上,而不是实际MYSQL去查完再决定的。都查完了,还用什么索引啊?!
MySQL会先估算,然后决定是否使用索引。
https://www.douban.com/note/345871485/

  1. 查看当前MYSQL支持的存储引擎
    show engines;
  2. 查看某一用户的权限
    show grants for UserName;
  3. 如何得知当前Binary Log文件和Position值
    show master status;
  4. 用什么命令切换Binary Log
    flush logs;
  5. 用什么命令修复MyISAM表
    repaire table TabName;
  6. 用什么命令整理表数据文件的碎片
    optimize table TabName;
  7. 如何得到TabA表的建表语句
    show create table TabA;
  8. 创建TabB表,完整拷贝TabA表的结构和索引,不要数据
    create table TabB like TabA;
  9. 为TabA表新增字段ColA,精度无偏差的小数型,10位整数,2位小数,加索引
    alter table TabA add ColA decimal(12,2), add key (ColA);
  10. 如何清空TabB表的数据
    truncate table TabB;
  11. 如何不进入mysql客户端,执行一条SQL命令,帐号User,密码Passwd,库名DBName,SQL为”select sysdate();”
    mysql -uUser -pPasswd -D DBName -e “select sysdate();”
  12. 如何从slow log中分析出所有的select语句,按次数以倒序输出前20条,日志名为slow_log.file
    mysqldumpslow -g ‘select’ -s c -r slow_log.file
  13. 如何从BinLog中分析出时间从”2012-10-27 13:00:00”到”2012-10-27 18:00:00”的anjuke库的SQL语句,日志名为bin_log.file
    mysqlbinlog -d anjuke –start-datetime=’2012-10-27 13:00:00’ –stop-datetime=’2012-10-27 18:00:00’ bin_log.file
  14. 创建用户,用户名为iamdba,密码为mypasswd,访问来源10.11.8.X,即8段IP都允许,对anjuke库所有表拥有“增删改查”权限
    grant insert,delete,update,select on anjuke.* to iamdba@’10.10.8.%’ identified by ‘mypasswd’;
  15. 如何执行一个SQL文件,帐号User,密码Passwd,库名DBName,SQL文件名为sql.file
    mysql -uUser -pPasswd -D DBName
  16. 用select方式导出TabA的所有数据到/tmp/TabA.txt文件
    select * from TabA into outfile ‘/tmp/TabA.txt’;
  17. 导入TabA.txt数据到TabB表,如主键或唯一键冲突,覆盖tabB表中的数据
    load data [local] infile ‘/tmp/TabA.txt’ replace into table TabB;
  18. 用mysqldump命令导出anjuke库里的TabB表中满足“ColA > 100”的数据到TabB.sql文件,不要导出建表语句,帐号User,密码Passwd
    mysqldump -uUser -pPasswd –no-create-info anjuke TabB -w “ColA > 100” >TabB.sql
    PS: –no-create-info 也可以写为 -t
  19. 切换同步到master 10.11.8.11,端口为3307,用户名repl,密码为passwd,起点BinLog为db-master.000001,位置123456
    change master to master_host=’10.11.8.11’, master_port=3307, master_user=’repl’, master_password=’passwd’, master_log_file=’db-master.000001’, master_log_pos=123456;
  20. 启动slave的sql进程,并在同步到master的db-master.000003文件123456位置上停止
    start slave sql_thread util master_log_file=’db-master.000003’, master_log_pos=123456;
  21. 建一个满足以下五种条件的最优索引
    where a=? and b=? and c=?
    where a=? and b>? and c=?
    where a=? and b in (?) and c=?
    where a=? and c=? order by b
    where a=? order by c,b
    创建顺序为(a,c,b)的复合索引
  22. 有二个复合索引(a,b)和(c,d),以下语句会怎样使用索引?可以做怎样的优化?
    select * from Tab where (a=? and b=?) or (c=? and d=?)
    根据MYSQL的机制,只会使用到一个筛选效果好的复合索引,可以做如下优化
    select * from Tab where a=? and b=?
    union
    select * from Tab where c=? and d=?
  23. 如何统计文件a.txt有多少非空行?
    grep -c ‘^..*’ a.txt  
    或  
    grep -v ‘^
    ’ a.txt | wc -l
  24. 文件b.txt,每行以“:”符分成5列,如“1:apple:3:2012-10-25:very good”,如何得到所有行第三列的总合值
    awk ‘BEGIN {FS=”:”; s=0} {s+=$3} END {print s}’ b.txt
  25. 截取文件c.txt的第60至480行记录,忽略大小写,统计出重复次数最多的那条记录,及重复次数
    sed -n ‘60,480’p c.txt | sort | uniq -i -c | sort -rn | head -n 1
    二、简答题 5x5
  26. MyISAM和InnoDB各有哪些特性?分别适用在怎样的场景下?
    MyISAM,表锁,不支持事务,表损坏率较高,分为MYD数据文件和MYI索引二个文件,读写并发不如InnoDB,适用于insert较多的场景,且支持直接复制文件,用以备份数据
    InnoDB,行锁,支持事务,crash后具有recove机制,只有ibd文件,分为数据区和索引区,有较好的读写并发能力,但做count()运算时相当消耗CPU
  27. MySQL原生支持的备份方式有哪些,并说出其优缺点?
    (1) 直接拷贝数据文件,必须是MyISAM表,且使用flush tables with read lock;语句,优点是简单方便,缺点是须要锁写,且只能在同版本的MySQL上恢复使用
    (2) mysqldump,导出的是SQL语句,所以可以跨版本恢复,但是需要导入数据和重建索引,恢复用时会较长,如果是MyISAM表,同样需要锁表,如果是InnoDB表,可以使用–single-transaction参数避免此问题
  28. 在创建和使用索引时,有哪些要注意的地方,有什么规则?
    避免索引过多,会影响写性能
    给筛选效果低的字段加索引,几乎无效,如性别、状态标志等
    每条查询执行时,只会使用一个索引,有需要时应该创建复合索引
    复合索引使用时遵守“从左到右”原则,严禁左百分号
    不要在索引字段上有运算操作和使用函数,将无法使用索引
  29. 如何分析一条SQL语句的执行性能,关注哪些信息?
    不论性能如何,不要有子查询和嵌套SQL,尽量不要有join查询
    使用explain命令,观察type列,可以知道是否是全表扫描,和索引的使用形式,观察key可以知道使用了哪个索引,观察key_len可以知道索引是否使用完成,观察rows可以知道扫描的行数是否过多,观察extra可以知道是否使用了临时表和进行了额外的排序操作
  30. MySQL通过什么机制来控制访问权限?
    mysql库中,从user表到host表和db表,再到tables_priv表和colums_priv表
    三、聊天题
  31. 对于一台DB服务器,有哪些是必须监控的基础指标,如何得到这些值?
  32. 简单介绍一个你用过的MYSQL状态探测或监控工具,第三方的或自己写的都可以,说出你觉得最好用的地方
  33. 简单介绍一个你用过的MySQL日志(slow/general/binary log)分析工具,第三方的或自己写的都可以,说出你觉得最好用的地方
  34. 介绍一件遇到过的DB服务器故障
  35. 如果出现Too many connections,应该采取哪些措施?
    http://bbs.it-home.org/thread-16612-1-1.html

where a=1 and b=1
where b=1
where b=1 order by time desc

请问这三条sql 如何建索引
只建一条怎么建

还有一个问题 就是 mysql 优化器会自动调整 where 条件的前后顺序吗
具体问题具体分析吧,mysql版本之间的差别比较大,需要针对不同的版本要看对索引的支持如何,
这三条查询中,b字段的查询频率最高,所以b字段要加入到索引中,多列索引中,索引的列顺序很重要。
只想建立单个索引,index(b,time)最合适。
“where a=1 and b=1”应该改为“where b=1 and a=1”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值