|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
不可否认,MySQL也是一个很好的关系型数据库,或许在技术上它与其他领先的关系数据库相差并不大,或不具有劣势。但是,对于一些企业环境来说,MySQL显然不具有优势。1、我们能够且应当优化甚么?
硬件
操纵体系/软件库
SQL服务器(设置和查询)
使用编程接口(API)
使用程序
2、优化硬件
假如你必要复杂的数据库表(>2G),你应当思索利用64位的硬件布局,像Alpha、Sparc或行将推出的IA64。由于MySQL外部利用大批64位的整数,64位的CPU将供应更好的功能。
对年夜数据库,优化的序次通常为RAM、疾速硬盘、CPU才能。
更多的内存经由过程将最经常使用的键码页面寄存在内存中能够减速键码的更新。
假如不利用事件平安(transaction-safe)的表或有年夜表而且想制止长文件反省,一台UPS就可以够在电源妨碍时让体系平安封闭。
关于数据库寄存在一个公用服务器的体系,应当思索1G的以太网。提早与吞吐量一样主要。
3、优化磁盘
为体系、程序和一时文件装备一个公用磁盘,假如确是举行良多修正事情,将更新日记和事件日记放在公用磁盘上。
低寻道工夫对数据库磁盘十分主要。对与年夜表,你能够估量你将必要log(行数)/log(索引块长度/3*2/(键码长度+数据指针长度))+1次寻到才干找到一行。关于有500000行的表,索引Mediunint范例的列,必要log(500000)/log(1024/3*2/(3+2))+1=4次寻道。上述索引必要500000*7*3/2=5.2M的空间。实践上,年夜多半块将被缓存,以是也许只必要1-2次寻道。
但是关于写进(如上),你将必要4次寻道哀求来找到在那里寄存新键码,并且一样平常要2次寻道来更新索引并写进一行。
关于十分年夜的数据库,你的使用将遭到磁盘寻道速率的限定,跟着数据量的增添呈NlogN数据级递增。
将数据库和表分在分歧的磁盘上。在MySQL中,你能够为此而利用标记链接。
条列磁盘(RAID0)将进步读和写的吞吐量。
带镜像的条列(RAID0+1)将更平安并进步读取的吞吐量。写进的吞吐量将有所下降。
不要对一时文件或能够很简单地重修的数据地点的磁盘利用镜像或RAID(除RAID0)。
在linux上,在引诱时对磁盘利用命令hdparm-m16-d1以启用同时读写多个扇区和DMA功效。这能够将呼应工夫进步5~50%。
在Linux上,用async(默许)和noatime挂载磁盘(mount)。
关于某些特定使用,能够对某些特定表利用内存磁盘,但一般不必要。
4、优化操纵体系
不要互换区。假如内存不敷,增添更多的内存或设置你的体系利用较少内存。
不要利用NFS磁盘(会有NFS锁定的成绩)。
增添体系和MySQL服务器的翻开文件数目。(在safe_mysqld剧本中到场ulimit-n#)。
增添体系的历程和线程数目。
假如你有绝对较少的年夜表,告知文件体系不要将文件打坏在分歧的磁道上(Solaris)。
利用撑持年夜文件的文件体系(Solaris)。
选择利用哪一种文件体系。在Linux上的Reiserfs关于翻开、读写都十分快。文件反省只需几秒种。
5、选择使用编程接口
PERL
可在分歧的操纵体系和数据库之间移植。
合适疾速原型。
应当利用DBI/DBD接口。
php
比PERL易学。
利用比PERL少的资本。
经由过程晋级到PHP4能够取得更快的速率。
C
MySQL的原生接口。
较快并付与更多的把持。
低层,以是必需支付更多。
C++
较高条理,给你更多的工夫来编写使用。
仍在开辟中
ODBC
运转在Windows和Unix上。
几近可在分歧的SQL服务器间移植。
较慢。MyODBC只是复杂的纵贯驱动程序,比用原生接口慢19%。
有良多办法做一样的事。很难像良多ODBC驱动程序那样运转,在分歧的范畴另有分歧的毛病。
成绩成堆。Microsoft偶然还会改动接口。
不开阔爽朗的将来。(Microsoft更推许OLE而非ODBC)
ODBC
运转在Windows和Unix上。
几近可在分歧的SQL服务器间移植。
较慢。MyODBC只是复杂的纵贯驱动程序,比用原生接口慢19%。
有良多办法做一样的事。很难像良多ODBC驱动程序那样运转,在分歧的范畴另有分歧的毛病。
成绩成堆。Microsoft偶然还会改动接口。
不开阔爽朗的将来。(Microsoft更推许OLE而非ODBC)
JDBC
实际上可在分歧的操纵体系什么时候据库间移植。
能够运转在web客户端。
Python和其他
大概不错,可我们不必它们。
6、优化使用
应当会合精神办理成绩。
在编写使用时,应当决意甚么是最主要的:
速率
操纵体系间的可移植性
SQL服务器间的可移植性
利用延续的毗连。.
缓存使用中的数据以削减SQL服务器的负载。
不要查询使用中不必要的列。
不要利用SELECT*FROMtable_name...
测试使用的一切部分,但将年夜部分精神放在在大概最坏的公道的负载下的测试全体使用。经由过程以一种模块化的体例举行,你应当能用一个疾速“哑模块”替换找到的瓶颈,然后很简单地标出下一个瓶颈。
假如在一个批处置中举行大批修正,利用LOCKTABLES。比方将多个UPDATES或DELETES会合在一同。
7、应当利用可移植的使用
PerlDBI/DBD
ODBC
JDBC
Python(或其他有广泛SQL接口的言语)
你应当只利用存在于一切目标SQL服务器中或能够很简单地用其他机关摹拟的SQL机关。www.mysql.com上的Crash-me页能够匡助你。
为操纵体系/SQL服务器编写包装程序来供应短少的功效。
8、假如你必要更快的速率,你应当:
找出瓶颈(CPU、磁盘、内存、SQL服务器、操纵体系、API或使用)并会合尽力办理。
利用赐与你更疾速度/天真性的扩大。
渐渐懂得SQL服务器以便能为你的成绩利用大概最快的SQL机关并制止瓶颈。
优化表结构和查询。
利用复制以取得更快的选择(select)速率。
假如你有一个慢速的收集毗连数据库,利用紧缩客户/服务器协定。
不关键怕时使用的第一个版本不克不及完善地移植,在你办理成绩时,你老是能够在今后优化它。
9、优化MySQL
选择编译器和编译选项。
位你的体系寻觅最好的启动选项。
通读MySQL参考手册并浏览PaulDuBios的《MySQL》一书。(已有中文版-译注)
多用EXPLAINSELECT、SHOWVARIABLES、SHOWSTATUS和SHOWPROCESSLIST。
懂得查询优化器的事情道理。
优化表的格局。
保护你的表(myisamchk、CHECKTABLE、OPTIMIZETABLE)
利用MySQL的扩大功效以让统统疾速完成。
假如你注重到了你将在良多场所必要某些函数,编写MySQLUDF函数。
不要利用表级或列级的GRANT,除非你的确必要。
购置MySQL手艺撑持以匡助你办理成绩:)
10、编译和安装MySQL
经由过程位你的体系选择大概最好的编译器,你一般能够取得10-30%的功能进步。
在Linux/Intel平台上,用pgcc(gcc的奔跑芯片优化版)编译MySQL。但是,二进制代码将只能运转在Intel奔跑CPU上。
关于一种特定的平台,利用MySQL参考手册上保举的优化选项。
一样平常地,对特定CPU的原生编译器(如Sparc的SunWorkshop)应当比gcc供应更好的功能,但不老是如许。
用你将利用的字符集编译MySQL。
静态编译天生mysqld的实行文件(用--with-mysqld-ldflags=all-static)并用stripsql/mysqld收拾终极的实行文件。
注重,既然MySQL不利用C++扩大,不带扩大撑持编译MySQL将博得伟大的功能进步。
假如操纵体系撑持原生线程,利用原生线程(而不必mit-pthreads)。
用MySQL基准测试来测试终极的二进制代码。
11、保护
假如大概,偶然运转一下OPTIMIZEtable,这对大批更新的变长行十分主要。
偶然用myisamchk-a更新一下表中的键码散布统计。记着在做之前关失落MySQL。
假如有碎片文件,大概值得将一切文件复制到另外一个磁盘上,扫除本来的磁盘并拷回文件。
假如碰到成绩,用myisamchk或CHECKtable反省表。
用mysqladmin-i10precesslistextended-status监控MySQL的形态。
用MySQLGUI客户程序,你能够在分歧的窗口内监控历程列表和形态。
利用mysqladmindebug取得有关锁定和功能的信息。
12、优化SQL
扬SQL之长,别的事变交由使用往做。利用SQL服务器来做:
找出基于WHERE子句的行。
JOIN表
GROUPBY
ORDERBY
DISTINCT
不要利用SQL来做:
查验数据(如日期)
成为一只盘算器
技能:
明智地利用键码。
键码合适搜刮,但不合适索引列的拔出/更新。
坚持数据为数据库第三范式,但不要忧虑冗余信息或这假如你必要更快的速率,创立总结表。
在年夜表上不做GROUPBY,相反创立年夜表的总结表并查询它。
UPDATEtablesetcount=count+1wherekey_column=constant十分快。
关于年夜表,也许最好偶然天生总结表而不是一向坚持总结表。
充实使用INSERT的默许值。
十3、分歧SQL服务器的速率不同(以秒计)
经由过程键码读取2000000行:NTLinux
mysql367249
mysql_odbc464
db2_odbc1206
informix_odbc121126
ms-sql_odbc1634
Oracle_odbc20800
solid_odbc877
sybase_odbc17614
拔出350768行:NTLinux
mysql381206
mysql_odbc619
db2_odbc3460
informix_odbc2692
ms-sql_odbc4012
oracle_odbc11291
solid_odbc1801
sybase_odbc4802
在上述测试中,MySQL设置8M高速缓存运转,其他数据库以默许安装运转。
十4、主要的MySQL启动选项
back_log假如必要大批新毗连,修正它。
thread_cache_size假如必要大批新毗连,修正它。
key_buffer_size索引页池,能够设成很年夜。
bdb_cache_sizeBDB表利用的纪录和键吗高速缓存。
table_cache假如有良多的表和并发毗连,修正它。
delay_key_write假如必要缓存一切键码写进,设置它。
log_slow_queries找出需花大批工夫的查询。
max_heap_table_size用于GROUPBY
sort_buffer用于ORDERBY和GROUPBY
myisam_sort_buffer_size用于REPAIRTABLE
join_buffer_size在举行无键吗的联合时利用。
十5、优化表
MySQL具有一套丰厚的范例。你应当对每列实验利用最无效的范例。
ANALYSE历程能够匡助你找到表的最优范例:SELECT*FROMtable_namePROCEDUREANALYSE()。
关于不保留NULL值的列利用NOTNULL,这对你想索引的列特别主要。
将ISAM范例的表改成MyISAM。
假如大概,用流动的表格局创立表。
不要索引你不想用的器材。
使用MySQL能按一个索引的前缀举行查询的现实。假如你有索引INDEX(a,b),你不必要在a上的索引。
不在长CHAR/VARCHAR列上创立索引,而只索引列的一个前缀以节俭存储空间。CREATETABLEtable_name(hostnameCHAR(255)notnull,index(hostname(10)))
对每一个表利用最无效的表格局。
在分歧表中保留不异信息的列应当有一样的界说并具有不异的列名。
十6、MySQL怎样次存储数据
数据库以目次存储。
表以文件存储。
列以变长或定长格局存储在文件中。对BDB表,数据以页面情势存储。
撑持基于内存的表。
数据库和表可在分歧的磁盘上用标记毗连起来。
在Windows上,MySQL撑持用.sym文件外部标记毗连数据库。
十7、MySQL表范例
HEAP表:流动行长的表,只存储在内存中并用HASH索引举行索引。
ISAM表:MySQL3.22中的初期B-tree表格局。
MyIASM:IASM表的新版本,有以下扩大:
二进制条理的可移植性。
NULL列索引。
对变长行比ISAM表有更少的碎片。
撑持年夜文件。
更好的索引紧缩。
更好的键吗统计散布。
更好和更快的auto_increment处置。
来自Sleepcat的BerkeleyDB(BDB)表:事件平安(有BEGINWORK/COMMIT|ROLLBACK)。
十8、MySQL行范例(专指IASM/MyIASM表)
假如一切列是定长格局(没有VARCHAR、BLOB或TEXT),MySQL将以定长表格局创立表,不然表以静态长度格局创立。
定长格局比静态长度格局快良多并更平安。
静态长度行格局一样平常占用较少的存储空间,但假如表频仍更新,会发生碎片。
在某些情形下,不值得将一切VARCHAR、BLOB和TEXT列转移到另外一个表中,只是取得主表上的更疾速度。
使用myiasmchk(对ISAM,pack_iasm),能够创立只读紧缩表,这使磁盘利用率最小,但利用慢速磁盘时,这十分不错。紧缩表充实天时用将不再更新的日记表
十9、MySQL高速缓存(一切线程共享,一次性分派)
键码缓存:key_buffer_size,默许8M。
表缓存:table_cache,默许64。
线程缓存:thread_cache_size,默许0。
主机名缓存:可在编译时修正,默许128。
内存映照表:今朝仅用于紧缩表。
注重:MySQL没有行高速缓存,而让操纵体系处置。
二10、MySQL缓存区变量(非共享,按需分派)
sort_buffer:ORDERBY/GROUPBY
record_buffer:扫描表。
join_buffer_size:无键联合
myisam_sort_buffer_size:REPAIRTABLE
net_buffer_length:关于读SQL语句并缓存了局。
tmp_table_size:一时了局的HEAP表巨细。
二11、MySQL表高速缓存事情道理
每一个MyISAM表的翻开实例(instance)利用一个索引文件和一个数据文件。假如表被两个线程利用或在统一条查询中利用两次,MyIASM将共享索引文件而是翻开数据文件的另外一个实例。
假如一切在高速缓存中的表都在利用,缓存将一时增添到比表缓存尺寸年夜些。假如是如许,下一个被开释的表将被封闭。
你能够经由过程反省mysqld的Opened_tables变量以反省表缓存是不是太小。假如该值太高,你应当增年夜表高速缓存。
二12、MySQL扩大/优化-供应更快的速率
利用优化的表范例(HEAP、MyIASM或BDB表)。
对数据利用优化的列。
假如大概利用定长行。
利用分歧的锁定范例(SELECTHIGH_PRIORITY,INSERTLOW_PRIORITY)
Auto_increment
REPLACE(REPLACEINTOtable_nameVALUES(...))
INSERTDELAYED
LOADDATAINFILE/LOAD_FILE()
利用多行INSERT一次拔出多行。
SELECTINTOOUTFILE
LEFTJOIN,STRAIGHTJOIN
LEFTJOIN,分离ISNULL
ORDERBY可在某些情形下利用键码。
假如只查询在一个索引中的列,将只利用索引树办理查询。
联合一样平常比子查询快(对年夜多半SQL服务器亦云云)。
LIMIT
SELECT*fromtable1WHEREa>10LIMIT10,20
DELETE*fromtable1WHEREa>10LIMIT10
fooIN(常数列表)高度优化。
GET_LOCK()/RELEASE_LOCK()
LOCKTABLES
INSERT和SELECT可同时运转。
UDF函数可装载进一个正在运转的服务器。
紧缩只读表。
CREATETEMPORARYTABLE
CREATETABLE..SELECT
带RAID选项的MyIASM表将文件支解成良多文件以冲破某些文件体系的2G限定。
Delay_keys
复制功效
二12、MySQL什么时候利用索引
对一个键码利用>,>=,=,<,<=,IFNULL和BETWEEN
SELECT*FROMtable_nameWHEREkey_part1=1andkey_part2>5;
SELECT*FROMtable_nameWHEREkey_part1ISNULL;
当利用不以通配符入手下手的LIKE
SELECT*FROMtable_nameWHEREkey_part1LIKEjani%
在举行联合时从另外一个表中提取行时
SELECT*fromt1,t2wheret1.col=t2.key_part
找出指定索引的MAX()或MIN()值
SELECTMIN(key_part2),MAX(key_part2)FROMtable_namewherekey_part1=10
一个键码的前缀利用ORDERBY或GROUPBY
SELECT*FROMfooORDERBYkey_part1,key_part2,key_part3
在一切用在查询中的列是键码的一部分工夫
SELECTkey_part3FROMtable_nameWHEREkey_part1=1
二十3、MySQL什么时候不利用索引
假如MySQL能估量出它将大概比扫描整张表还要快时,则不利用索引。比方假如key_part1匀称散布在1和100之间,以下查询中利用索引就不是很好:
SELECT*FROMtable_namewherekey_part1>1andkey_part1<90
假如利用HEAP表且不必=搜刮一切键码部分。
在HEAP表上利用ORDERBY。
假如不是用键码第一部分
SELECT*FROMtable_nameWHEREkey_part2=1
假如利用以一个通配符入手下手的LIKE
SELECT*FROMtable_nameWHEREkey_part1LIKE%jani%
搜刮一个索引而在另外一个索引上做ORDERBY
SELECT*fromtable_nameWHEREkey_part1=#ORDERBYkey2
二十4、学会利用EXPLAIN
关于每条你以为太慢的查询利用EXPLAIN!
mysql>explainselectt3.DateOfAction,t1.TransactionID
->fromt1joint2joint3
->wheret2.ID=t1.TransactionIDandt3.ID=t2.GroupID
->orderbyt3.DateOfAction,t1.TransactionID;
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
|table|type|possible_keys|key|key_len|ref|rows|Extra|
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
|t1|ALL|NULL|NULL|NULL|NULL|11|Usingtemporary;Usingfilesort|
|t2|ref|ID|ID|4|t1.TransactionID|13||
|t3|eq_ref|PRIMARY|PRIMARY|4|t2.GroupID|1||
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
ALL和局限范例提醒一个潜伏的成绩。
二十5、学会利用SHOWPROCESSLIST
利用SHOWprocesslist来发明正在做甚么:
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
|Id|User|Host|db|Command|Time|State|Info|
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
|6|monty|localhost|bp|Query|15|Sendingdata|select*fromstation,stationass1|
|8|monty|localhost||Query|0||showprocesslist|
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
在mysql或mysqladmin顶用KILL来杀逝世溜失落的线程。
二十6、怎样晓得MySQL办理一条查询
运转项列命令并试图弄分明其输入:
SHOWVARIABLES;
SHOWCOLUMNSFROM...G
EXPLAINSELECT...G
FLUSHSTATUS;
SELECT...;
SHOWSTATUS;
二十7、MySQL十分不错
日记
在举行良多毗连时,毗连十分快。
同时利用SELECT和INSERT的场所。
在不把更新与耗时太长的选择分离时。
在年夜多半选择/更新利用独一键码时。
在利用没有长工夫抵触锁定的多个表时。
在用年夜表时(MySQL利用一个十分松散的表格局)。
二十8、MySQL应制止的事变
用删失落的行更新或拔出表,分离要耗时长的SELECT。
在能放在WHERE子句中的列上用HAVING。
不利用键码或键码不敷独一而举行JOIN。
在分歧列范例的列上JOIN。
在不利用=婚配全部键码时利用HEAP表。
在MySQL监控程序中健忘在UPDATE或DELETE中利用一条WHERE子句。假如想如许做,利用mysql客户程序的--i-am-a-dummy选项。
二十9、MySQL各类锁定
外部表锁定
LOCKTABLES(一切表范例合用)
GETLOCK()/RELEASELOCK()
页面锁定(对BDB表)
ALTERTABLE也在BDB表长进行表锁定
LOCKTABLES同意一个表有多个读者和一个写者。
一样平常WHERE锁定具有比READ锁定高的优先级以免让写进方干等。关于不主要的写进方,可使用LOW_PRIORITY关头字让锁定处置器优选读取方。
UPDATELOW_PRIORITYSETvalue=10WHEREid=10;
三10、给MySQL更多信息以更好地办理成绩的技能
注重你总能往失落(加正文)MySQL功效以使查询可移植:
SELECT/*!SQL_BUFFER_RESULTS*/...
SELECTSQL_BUFFER_RESULTS...
将强迫MySQL天生一个一时了局集。只需一切一时了局集天生后,一切表上的锁定均被开释。这能在碰到表锁定成绩时或要花很长工夫将了局传给客户端时有所匡助。
SELECTSQL_SMALL_RESULT...GROUPBY...
告知优化器了局集将只包括很少的行。
SELECTSQL_BIG_RESULT...GROUPBY...
告知优化器了局集将包括良多行。
SELECTSTRAIGHT_JOIN...
强迫优化器以呈现在FROM子句中的序次联合表。
SELECT...FROMtable_name[USEINDEX(index_list)|IGNOREINDEX(index_list)]table_name2
强迫MySQL利用/疏忽列出的索引。
三11、事件的例子
MyIASM表怎样举行事件处置:
mysql>LOCKTABLEStransREAD,customerWRITE;
mysql>selectsum(value)fromtranswherecustomer_id=some_id;
mysql>updatecustomersettotal_value=sum_from_previous_statement
wherecustomer_id=some_id;
mysql>UNLOCKTABLES;
BDB表怎样举行事件:
mysql>BEGINWORK;
mysql>selectsum(value)fromtranswherecustomer_id=some_id;
mysql>updatecustomersettotal_value=sum_from_previous_statement
wherecustomer_id=some_id;
mysql>COMMIT;
注重你能够经由过程以下语句躲避事件:
UPDATEcustomerSETvalue=value+new_valueWHEREcustomer_id=some_id;
三12、利用REPLACE的例子
REPLACE的功效极像INSERT,除假如一条老纪录在一个独一索引上具有与新记录不异的值,那末老纪录在新记录拔出前则被删除。不利用
SELECT1FROMt1WHEREkey=#
IFfound-row
LOCKTABLESt1
DELETEFROMt1WHEREkey1=#
INSERTINTOt1VALUES(...)
UNLOCKTABLESt1;
ENDIF
而用
REPLACEINTOt1VALUES(...)
三十3、一样平常技能
利用短主键。联合表时利用数字而非字符串。
当利用多部分键码时,第一部分应当时最经常使用的部分。
有疑问时,起首利用更多反复的列以取得更好地键码紧缩。
假如在统一台呆板上运转MySQL客户和服务器,那末在毗连MySQL时则利用套接字而不是TCP/IP(这能够进步功能7.5%)。可在毗连MySQL服务器时不指定主机名或主机名为localhost来做到。
假如大概,利用--skip-locking(在某些OS上为默许),这将封闭内部锁定并将进步功能。
利用使用层哈希值而非长键码:
SELECT*FROMtable_nameWHEREhash=md5(concat(col1,col2))AND
col_1=constantANDcol_2=constant
在文件中保留必要以文件情势会见的BLOB,在数据库中只保留文件名。
删除一切行比删除一年夜部分行要快。
假如SQL不敷快,研讨一下会见数据的较底层接口。
三十4、利用MySQL3.23的优点
MyISAM:可移植的年夜表格局
HEAP:内存中的表
BerkeleyDB:撑持事件的表。
浩瀚进步的限定
静态字符集
更多的STATUS变量
CHECK和REPAIR表
更快的GROUPBY和DISTINCT
LEFTJOIN...IFNULL的优化
CREATETABLE...SELECT
CREATETEMPORARYtable_name(...)
一时HEAP表到MyISAM表的主动转换
复制
mysqlhotcopy剧本
三十5、正在主动开辟的主要功效
改善事件处置
失利平安的复制
注释搜刮
多个表的删除(以后完成多个表的更新)
更好的键码缓存
原子RENAME(RENAMETABLEfooasfoo_old,foo_newasfoo)
查询高速缓存
MERGETABLES
一个更好的GUI客户程序
这一切听起来不错,无疑DBaaS具有很多相对于RDBMS的优势。然而MySQL学习教程,DBaaS也有其局限性,云服务中固有的局限性就是之一。当客户开始将数据放入云端时,他们会遭遇到无法控制的网络性能问题。 |
|