??xml version="1.0" encoding="utf-8" standalone="yes"?> 表空间是逻辑存放所有数据的地方Q默认情况下会共享一个表I间——ibdata1Q但如果?/span>innodb_file_per_table=ON后每张表可以单独攑ֈ一个表I间内,但还是有很多数据保存在共享的?/span>ibdata1中,?/span>undo信息{?/span> 表空间由各种D?/span>(segment)l成Q常见的D|数据Dc烦引段{?/span>Innodb是烦引组l的Q数据段是clustered index的叶l点。需要注意的是,不是每个对象都有Dc?/span> ?/span>(extend)是由64个连l的늻成,每个(pageQ固定ؓ16KBQ所以每个区d?/span>1M。页?/span>innodb最的盘理单位?/span> Innodb是按行进行存攄Q每个区最可以保?/span>2条记录,否则成铑ּl构了。每行数据除了自定义列以外,q会增加事务id和回滚指针列。如果没有定?/span>primary key也没?/span>not null?/span>unique,则会增加6字节?/span>RowId列作Z键?br /> 一个表不能包含过1000列?/span> 内部最大键长度?/span>3500字节Q但MySQL自己限制q个?/span>1024字节?/span> 除了VARCHAR, BLOB?/span>TEXT列,最大行长度E微于数据库页的一半。即Q最大行长度大约8000字节?/span>LONGBLOB?/span>LONGTEXT列必d?/span>4GB, ȝ行长度,包?/span>BLOB?/span>TEXT列,必须于4GB?/span>InnoDB在行中存?/span>VARCHARQ?/span>BLOB?/span>TEXT列的?/span>768字节Q余下的存储的分散的中?/span> 虽然InnoDB内部地支持行寸大于65535Q你不能定义一个包?/span>VARCHAR列的Q合q尺寸大?/span>65535的行?/span> · mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000), · -> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000), · -> f VARCHAR(10000), g VARCHAR(10000)); · ERROR 1118 (42000): Row size too large. The maximum row size for the · used table type, not counting BLOBs, is 65535. You have to change some · columns to TEXT or BLOBs 在一些更老的操作pȝ上,数据文g必须于2GB?/span> InnoDB日志文g的合q尺寸必d?/span>4GB?/span> 最的表空间尺寸是10MB。最大的表空间尺寸是4,000,000,000个数据库(64TBQ。这也是一个表的最大尺寸?/span> InnoDB表不支持FULLTEXT索引 默认情况?/span>Memory使用存储hash索引Q但也支?/span>b+tree索引?/span>Hash索引只用?/span>=或?/span><=>的等式比较,不能用来加?/span>order by操作Q只能通过关键字来搜烦一行?/span>innodb只支?/span>b+树烦引,q一步分?/span>clustered index 与 secondary index。在一ơ查询中Q只能用一个烦引?/span> Innodb是烦引组l表Q?/span>clustered index的叶l点保存着整行的数据。如果,定义?/span>primary keyQ则clustered index是primary key的烦引;如果没有定义primary key mysql会选中W一个仅?/span>not null列的unique索引作ؓ主键Qƈ把此索引当作clustered index使用Q如果没扑ֈq样的列Q?/span>innodb会创Z?/span>6字节?/span>RowId作ؓ主键。所以每张表有且只有一?/span>clustered index?/span> Secondary index的叶l点不包括行的全部数据,包含键g外还包括一?/span>bookmarkQ可以告?/span>innodbC么地方可以找到相对应的完整行数据Q还保存了主键的健倹{?/span>Secondary index包含主键Q但不包含完整的行数据,所?/span>innodbL会先?/span>secondary index的叶节点判断是否能得到所需的数据。如, Create table t(a int, b varchar(20), primary key(a), key(b)); Explain select * from t; 会发?/span>mysql选择了烦?/span>bQ而不?/span>a. 复合索引是在多列Q?/span>>=2Q上建立的烦引,又叫多列索引或联合烦引?/span>Innodb中的复合索引也是b+ treel构。烦引的数据包含多列(col1, col2, col3…)Q在索引中依ơ按?/span>col1, col2, col3排序。如(1, 2), (1, 3),(2,0)… 使用复合索引要充分利用最左前~原则Q顾名思义Q就是最左优先。如创徏索引ind_col1_col2(col1, col2)Q那么在查询where col1 = xxx and col2 = xx或?/span>where col1 = xxx都可以走ind_col1_col2索引?/span> 在创建多列烦引时Q要Ҏ业务需求,where子句中用最频繁且过滤效果好的的一列放在最左边?/span> 可以通过DML语句操作innodb索引。因?/span>innodb是烦引组l的表,对烦引的操作会造成锁表Q先生成一张时表Q将数据从原始表中写C时表Q再原始表删除Q最后将临时表表名改为原始表表名Q因增加、删除、修改字D会对主索引产生影响Q所以也会锁表。对secondary index?/span>Innodb plugin开始,支持快速烦引创建的ҎQ在创徏的过E中不需要重Q所以速度会很快,同时引擎会在表上?/span>S锁,在创E中只能q行L作?/span> 1. 搜烦的烦引列Q不一定是所要选择的列。也是_最适合索引的列是出现在where子句中的列,或者连接子句中指定的列Q而不是出现在select关键字后的选择列表中的列?/span> 2. 使用唯一索引。考虑某列的分布,索引的列的基数越大,索引的效果越好。例如,Ҏ别M/F列做索引没多大用处?/span> 3. 使用短烦引。如果是对字W串q行索引Q如果有可能应该指定前缀长度?/span> 4. 利用最左前~。尽量将使用频繁且过滤效果好的字D|“左边” 5. 不要q度索引?/span> 6. Innodb默认会按照一定的序保存数据Q如果明定义了主键Q则按照主键序保存。如果没有主键,但有唯一索引Q就按照唯一索引的顺序保存。如果有几个列都是唯一的,都可以作Z键的时候,Z提高查询效率Q应选择最常用讉K的列作ؓ主键。另外,innodb?/span>secondary index都会保存主键的键|所有主键要可能选择较短的数据类型。可以看出,应当量避免对主键的修改。经q?/span>dba的测试,保证主键的递增可以提高插入性能?/span> 1. 对于创徏的多列烦引,只要查询的条件中用到了最左边的列Q烦引一般就会被使用?/span> 2. 对于使用like的查询,后面如果是常量ƈ且只?/span>%号不在第一个字W,索引才可能被使用?/span> 3. 如果对大文本q行搜烦Q应该用全文烦引,而不是?/span>like ‘%...%’. 但不q的?/span>innodb不支持全文烦引?/span> 4. 如果列名是烦引,使用 index_column is null用烦引?/span>Oracle是不行的?/span> 5. 如果mysql估计使用索引比全表扫描更慢,最不会使用索引?/span> 6. 如果使用memory/head表ƈ?/span>where条g中不使用”=”q行索引列,那么不会用到索引?/span>Head表只有在”=”的时候才会用烦引?/span> 7. ?/span>or分割开的条Ӟ如果or前的条g中的列有索引Q而后面列中没有烦引,那么涉及到的索引都不会被用到?/span> 8. 不是多列索引的第一部分不会走烦引?/span> 9. ?/span>%开始的like不会走烦?/span> 10. 如果列是字符Ԍ那么一定要?/span>where条g中把字符串常量值用引号引v来,否则不能走烦引。因为,mysql默认把输入的帔RD行{换以后才q行索?/span> 11. l过普通运或函数q算后的索引字段不能使用索引 12. 不等于操作不能用烦Q?/span><>?/span>not in{?/span> 13. Order by 优化Q某些情况下Q?/span>mysql可以使用一个烦引满?/span>order by,而不需要额外的排序?/span>Where条g?/span>order by 使用相同的烦引,q且order by的顺序和索引序相同Qƈ?/span>order by的字D都是升序或者都是降序?/span> SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC; 但是以下情况不用烦引: SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC Q?/span> --order by 的字D|?/span> ASC ?/span> DESC SELECT * FROM t1 WHERE key2=constant ORDER BY key1 Q?/span> -- 用于查询行的关键字与 ORDER BY 中所使用的不相同 SELECT * FROM t1 ORDER BY key1, key2 Q?/span> -- 对不同的关键字?/span> ORDER BY 可以使用explain查看sql的执行计划?/span> 每一?/span>try语句?/span>catch的异帔R与异常表中的一相对应Q异常表中的每一w包括Q?/span> 例如Q?/p>
?/span>javap –c查看字节码如下: 可见ClassNotFoundException异常可能会在0~6之间抛出Q?/span>9开始处的代码处理此异常?/span> 当生异常的时候,jvm会在整个异常表中搜索与之匹配的,如果当前pc在异常表入口所指的范围内,q且所抛出的异常是此入口所指向的类或者其子类Q则跌{到对应的处理代码l箋执行?/span> Class文g?/span>attribute_info中保存有Exceptions属性,记录着每个Ҏthrows的异怿息。具体的可以查看classcL件格式相关的文章?/span> athrow指o从栈弹?/span>Throwable对象引用Q抛出异常?/span> ?/span>jvm规范中,finally语句是通过jsr/jsr_w?/span>ret指o实现的。当执行jsr/jsr_w的时候将finally执行完成后的q回地址压入栈中Q进?/span>finally后会马上此地址保存C个局部变量中Q执行完成后Q?/span>ret从此局部变量中取出q回地址。?Q?Z么会先把q回地址保存到局部变量中呢?Q?因ؓQ当?/span>finally语句q回的时候需要将q回地址成栈中弹出,?/span>finally语句非正常结?/span>(break,continue,return, 抛异?/span>)的时候就不用再考虑q个问题?/span> 以下?/span>jvm规范?/span>Compiling finally的一D: ?/span>tryItOut排除M异常后都会被异常表中的anyҎP执行?/span>finally后,会执?/span>athrow指o异常抛出?/span> ?/span>jdk的某一个版本开始就不会~译出编译出?/span>jsr/jsr_w?/span>ret的字节码了,因ؓ有指令上的缺PDjvm的检验和分析pȝ出现漏洞?/span> ?/span>finally中?/span>break?/span>continue?/span>return、抛出异常等认ؓ?/span>finally的非正常l束。非正常l束的时候,ret指o不会被执行,很可能会出现意想不到的结果。如Q?/span>
囄来自Q?a >http://www.cnblogs.com/chjw8016/archive/2011/03/08/1976891.htmlInnodb表的限制
Innodb索引
复合索引
索引操作
索引设计原则
Mysql如何使用索引
Bridge methods in Java are synthetic methods, which are necessary to implement some of Java language features. The best known samples are covariant return type and a case in generics when erasure of base method's arguments differs from the actual method being invoked.
Have a look at following example:
public static class A<T> {
public T getT() {
return null;
}
}
public static class B extends A<String> {
public String getT() {
return null;
}
}
}
public static class A {
public Object getT() {
return null;
}
}
public static class B extends A {
public String getT() {
return null;
}
}
}
And after the compilation decompiled result class "B" will be following:
public SampleOne$B();
public java.lang.String getT();
Code:
0: aconst_null
1: areturn
public java.lang.Object getT();
Code:
0: aload_0
1: invokevirtual #2; // Call to Method getT:()Ljava/lang/String;
4: areturn
}
Above you can see there is new synthetic method "java.lang.Object getT()" which is not present in source code. That method acts as bridge method and all is does is delegating invocation to "java.lang.String getT()". Compiler has to do that, because in JVM method return type is part of method's signature, and creation of bridge method is the way to implement covariant return type.
Now have a look at following example which is generics-specific:
public class SampleTwo {
public static class A<T> {
public T getT(T args) {
return args;
}
}
public static class B extends A<String> {
public String getT(String args) {
return args;
}
}
}
after compilation class "B" will be transformed into following:
public class SampleThree$B extends SampleThree$A{
public SampleThree$B();
public java.lang.String getT(java.lang.String);
Code:
0: aload_1
1: areturn
public java.lang.Object getT(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: checkcast #2; //class java/lang/String
5: invokevirtual #3; //Method getT:(Ljava/lang/String;)Ljava/lang/String;
8: areturn
}
here, the bridge method, which overrides method from base class "A", not just calling one with string argument (#3), but also performs type cast to "java.lang.String" (#2). It means, that if you will execute following code, ignoring compiler's "unchecked" warning, the result will be ClassCastException thrown from the bridge method:
A a = new B();
a.getT(new Object()));
These two examples are the best known cases where bridge methods are used, but there is, at least, one more, where bridge method is used to "change" visibility of base class's methods. Have a look at following sample and try to guess where compiler may need the bridge method to be created:
package samplefour;
public class SampleFour {
static class A {
public void foo() {
}
}
public static class C extends A {
}
public static class D extends A {
public void foo() {
}
}
}
public class SampleFour$C extends SampleFour$A{
public void foo();
Code:
0: aload_0
1: invokespecial #2; //Method SampleFour$A.foo:()V
4: return
}
compiler needs that method, because class A is not public and can't be accessed outside it's package, but class C is public and all inherited method have to become visible outside the package as well. Note, that class D will not have bridge method, because it overrides "foo" and there is no need to "increase" visibility.
It looks like, that type of bridge method, was introduced after bug which was fixed in Java 6. It means that before Java 6 that type of bridge method is not generated and method "C#foo" can't be called from package other than it's own via reflection, so following snippet causes IllegalAccessException, in cases when compiled on Java version < 1.6:
package samplefive;
SampleFour.C.class.getMethod("foo").invoke(new SampleFour.C());
Probably there are some other cases where bridge methods are used, but there is no source of information about it. Also, there is no definition of bridge method, although you can guess it easily, it's pretty obvious from examples above, but still would be nice to have something in spec which states it clearly. In spite of the fact that method Method#isBridge() is part of public reflection API since Java1.5 and bridge flag is part of class file format, JVM and JLS specifications do not have any information what exactly is that and do not provide any rules when and how it should be used by compiler. All I could find is just reference in "Discussion" area here.public class Test {
public static void main(String[] args) {
try {
Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String java.lang.String
2: invokestatic #3; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
5: pop
6: goto 14
9: astore_1
10: aload_1
11: invokevirtual #5; //Method java/lang/ClassNotFoundException.printStackTrace:()V
14: return
Exception table:
from to target type
0 6 9 Class java/lang/ClassNotFoundException
}
Ҏ可能会抛出哪些已查异?/span>
finally语句
void tryFinally() {
try {
tryItOut();
} finally {
wrapItUp();
}
}
the compiled code is
Method void tryFinally()
0 aload_0 // Beginning of try block
1 invokevirtual #6 // Method Example.tryItOut()V
4 jsr 14 // Call finally block
7 return // End of try block
8 astore_1 // Beginning of handler for any throw
9 jsr 14 // Call finally block
12 aload_1 // Push thrown value
13 athrow //
and rethrow the value to the invoker
14 astore_2 // Beginning of finally block
15 aload_0 // Push this
16 invokevirtual #5 // Method Example.wrapItUp()V
19 ret 2 // Return from finally block
Exception table:
From To Target Type
0 4 8 any
再说finally的非正常退?/span>
public class Test {
public static boolean test(boolean b) {
while (b) {
try {
return true;
} finally {
/*
break; 始终q回false
continue; javac~译再java执行会出现死循环
在eclipse中甚至会出现报错Q提C找Cmain class
return false; 始终q回false
throw new RuntimeException(""); 抛出异常
*/
}
}
return false;
}
public static void main(String[] args) {
System.out.println(test(true));
}
}
Q在?/span>finally语句的时候,量避免非正常结束!
单库单表是最常见的数据库设计Q例如,有一张用?span lang="EN-US">(user)表放在数据库db中,所有的用户都可以在db库中?span lang="EN-US">user表中查到?/p>
随着用户数量的增加,user表的数据量会来大Q当数据量达C定程度的时候对user表的查询会渐渐的变慢Q从而媄响整?span lang="EN-US">DB的性能。如果?span lang="EN-US">mysql, q有一个更严重的问题是Q当需要添加一列的时候,mysql会锁表,期间所有的d操作只能{待?/p>
可以通过某种方式?span lang="EN-US">userq行水^的切分,产生两个表结构完全一Luser_0000,user_0001{表Q?span lang="EN-US">user_0000 + user_0001 + …的数据刚好是一份完整的数据?/p>
随着数据量增加也许单?span lang="EN-US">DB的存储空间不够,随着查询量的增加单台数据库服务器已经没办法支撑。这个时候可以再Ҏ据库q行水^区分?/p>
设计表的时候需要确定此表按照什么样的规则进行分库分表。例如,当有新用hQ程序得定此用户信息d到哪个表中;同理Q当d的时候我们得通过用户的̎h到数据库中对应的记录Q所有的q些都需要按照某一规则q行?/p>
通过分库分表规则查找到对应的表和库的q程。如分库分表的规则是user_id mod 4的方式,当用h注册了一个̎P账号id?span lang="EN-US">123,我们可以通过id mod 4的方式确定此账号应该保存?span lang="EN-US">User_0003表中。当用户123d的时候,我们通过123 mod 4后确定记录在User_0003中?/p>
1. 分库分表l度的问?/p>
假如用户购买了商?span lang="EN-US">,需要将交易记录保存取来Q如果按照用LU度分表Q则每个用户的交易记录都保存在同一表中Q所以很快很方便的查扑ֈ某用L购买情况Q但是某商品被购买的情况则很有可能分布在多张表中Q查找v来比较麻烦。反之,按照商品l度分表Q可以很方便的查扑ֈ此商品的购买情况Q但要查扑ֈCh的交易记录比较麻烦?/p>
所以常见的解决方式有:
a.通过扫表的方式解冻I此方法基本不可能Q效率太低了?/p>
b.记录两䆾数据Q一份按照用L度分表,一份按照商品维度分表?/p>
c.通过搜烦引擎解决Q但如果实时性要求很高,又得关系到实时搜索?/p>
2. 联合查询的问?/p>
联合查询基本不可能,因ؓ兌的表有可能不在同一数据库中?/p>
3. 避免跨库事务
避免在一个事务中修改db0中的表的时候同时修?span lang="EN-US">db1中的表,一个是操作h更复杂,效率也会有一定媄响?/p>
4. 量把同一l数据放到同一DB服务器上
例如卖?span lang="EN-US">a的商品和交易信息都放?span lang="EN-US">db0中,?span lang="EN-US">db1挂了的时候,卖家a相关的东西可以正怋用。也是说避免数据库中的数据依赖另一数据库中的数据?/p>
在实际的应用中,l大部分情况都是读远大于写?span lang="EN-US">Mysql提供了读写分ȝ机制Q所有的写操作都必须对应?span lang="EN-US">MasterQ读操作可以?span lang="EN-US">Master?span lang="EN-US">Slave机器上进行,Slave?span lang="EN-US">Master的结构完全一P一?span lang="EN-US">Master可以有多?span lang="EN-US">Slave,甚至Slave下还可以?span lang="EN-US">Slave,通过此方式可以有效的提高DB集群?span lang="EN-US">QPS.
所有的写操作都是先?span lang="EN-US">Master上操作,然后同步更新?span lang="EN-US">Slave上,所以从Master同步?span lang="EN-US">Slave机器有一定的延迟Q当pȝ很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会ɘq个问题更加严重?/p>
此外Q可以看?span lang="EN-US">Master是集的瓉Q当写操作过多,会严重媄响到Master的稳定性,如果Master挂掉Q整个集都不能正常工作?/p>
所以,1. 当读压力很大的时候,可以考虑dSlave机器的分式解冻I但是?span lang="EN-US">Slave机器辑ֈ一定的数量得考虑分库了?span lang="EN-US"> 2. 当写压力很大的时候,必dq行分库操作?/p>
另外Q可能会因ؓU种原因Q集中的数据库g配置{会不一P某些性能高,某些性能低,q个时候可以通过E序控制每台机器d的比重,辑ֈ负蝲均衡?/p>
备䆾地址Q?span style="font-family: Simsun; line-height: normal; font-size: medium; ">http://happyenjoylife.iteye.com/admin/blogs/1042538
1. 安装mercurial
Mercurial是一个版本管理工兗?/span>
sudo apt-get install mercurial
安装mercurial的扩展,dfclone在支?/span>
hg clone http://bitbucket.org/pmezard/hgforest-crew
以下内Ҏ加到$HOME/.hgrc文g中,如果没有则自己创Z个:
[extensions]
forest=/home/daren/hgforest-crew/forest.py
fetch=
2. 下蝲jdk7源码
hg fclone http://hg.openjdk.java.net/jdk7/jdk7
3. 安装gcc?/span>g++?/span>make{?/span>
sudo apt-get install build-essential
4. 安装XRender
sudo apt-get install libxrender-dev
sudo apt-get install xorg-dev
5. 安装alsa
sudo apt-get install libasound2-dev
6. Cups
sudo apt-get install libcups2-dev
7. 安装jdk6
8. 安装ant
讄ANT_HOME
9. 安装findbugs
~译需要这玩意儿有点奇怪。需要设|?/span>FINDBUGS_HOME
10. 试~译
export LANG=C ALT_BOOTDIR=/opt/jdk1.6.0_22/
#删除JAVA_HOME
export -n JAVA_HOME
export ALT_JDK_IMPORT_PATH=/opt/jdk1.6.0_22/
make sanity BUILD_JAXWS=false BUILD_JAXP =false
?/span>build BUILD_JAXWS?/span>BUILD_JAXPL提示找不到源文gQ而我又暂时对只对JDK?/span>Hotspot感兴,所以烦性把q两个给L?/span>
如果出现:Sanity check passed.则表C测试编译通过了,不过也别开心得太早Q真?/span>make的时候不保证一定没问题Q也许还会缺某些依赖?/span>
11. ~译
export LANG=C ALT_BOOTDIR=/opt/jdk1.6.0_22/
#删除JAVA_HOME
export -n JAVA_HOME
export ALT_JDK_IMPORT_PATH=/opt/jdk1.6.0_22/
#make BUILD_JAXWS=false BUILD_JAXP=false
#make DEBUG_NAME=fastdebug BUILD_JAXWS=false BUILD_JAXP=false
make DEBUG_NAME=all_fastdebug BUILD_JAXWS=false BUILD_JAXP=false
如果一切正常的话在$HOME/jdk7/build/linux-i586/下就?/span>build出来?/span>jdk{了?/span>