<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    2011年5月27日

    Innodb存儲

    表空間是邏輯存放所有數(shù)據(jù)的地方,默認(rèn)情況下會共享一個表空間——ibdata1,但如果把innodb_file_per_table=ON后每張表可以單獨(dú)放到一個表空間內(nèi),但還是有很多數(shù)據(jù)保存在共享的表ibdata1中,如undo信息等。

     

    表空間由各種段(segment)組成,常見的段有數(shù)據(jù)段、索引段等。Innodb是索引組織的,數(shù)據(jù)段就是clustered index的葉結(jié)點(diǎn)。需要注意的是,不是每個對象都有段。

     

    區(qū)(extend)是由64個連續(xù)的頁組成,每個頁(page)固定為16KB,所以每個區(qū)總共為1M。頁是innodb最小的磁盤管理單位。

     

    Innodb是按行進(jìn)行存放的,每個區(qū)最少可以保存2條記錄,否則就成鏈?zhǔn)浇Y(jié)構(gòu)了。每行數(shù)據(jù)除了自定義列以外,還會增加事務(wù)id和回滾指針列。如果沒有定義primary key也沒有not nullunique,則會增加6字節(jié)的RowId列作為主鍵。
            
                圖片來自:http://www.cnblogs.com/chjw8016/archive/2011/03/08/1976891.html

    Innodb表的限制

            一個表不能包含超過1000列。

      內(nèi)部最大鍵長度是3500字節(jié),但MySQL自己限制這個到1024字節(jié)。

      除了VARCHAR, BLOBTEXT列,最大行長度稍微小于數(shù)據(jù)庫頁的一半。即,最大行長度大約8000字節(jié)。LONGBLOBLONGTEXT列必須小于4GB, 總的行長度,頁包括BLOBTEXT列,必須小于4GBInnoDB在行中存儲VARCHARBLOBTEXT列的前768字節(jié),余下的存儲的分散的頁中。

    雖然InnoDB內(nèi)部地支持行尺寸大于65535,你不能定義一個包含VARCHAR列的,合并尺寸大于65535的行。

    ·                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

     在一些更老的操作系統(tǒng)上,數(shù)據(jù)文件必須小于2GB

     InnoDB日志文件的合并尺寸必須小于4GB

    最小的表空間尺寸是10MB。最大的表空間尺寸是4,000,000,000個數(shù)據(jù)庫頁(64TB)。這也是一個表的最大尺寸。

     InnoDB表不支持FULLTEXT索引

     

    Innodb索引

    默認(rèn)情況下Memory使用存儲hash索引,但也支持b+tree索引。Hash索引只用于=或者<=>的等式比較,不能用來加速order by操作,只能通過關(guān)鍵字來搜索一行。innodb只支持b+樹索引,進(jìn)一步分為clustered index 與 secondary index。在一次查詢中,只能使用一個索引。

            

    Innodb是索引組織表,clustered index的葉結(jié)點(diǎn)保存著整行的數(shù)據(jù)。如果,定義了primary key,則clustered index就是primary key的索引;如果沒有定義primary key mysql會選中第一個僅有not null列的unique索引作為主鍵,并把此索引當(dāng)作clustered index使用;如果沒找到這樣的列,innodb會創(chuàng)建一個6字節(jié)的RowId作為主鍵。所以每張表有且只有一個clustered index

     

             Secondary index的葉結(jié)點(diǎn)不包括行的全部數(shù)據(jù),包含鍵值以外還包括一個bookmark,可以告訴innodb到什么地方可以找到相對應(yīng)的完整行數(shù)據(jù),還保存了主鍵的健值。Secondary index包含主鍵,但不包含完整的行數(shù)據(jù),所以innodb總是會先從secondary index的葉節(jié)點(diǎn)判斷是否能得到所需的數(shù)據(jù)。如,

             Create table t(a int, b varchar(20), primary key(a), key(b));

    Explain select * from t;

             會發(fā)現(xiàn)mysql選擇了索引b,而不是a.

    復(fù)合索引

             復(fù)合索引是在多列(>=2)上建立的索引,又叫多列索引或聯(lián)合索引。Innodb中的復(fù)合索引也是b+ tree結(jié)構(gòu)。索引的數(shù)據(jù)包含多列(col1, col2, col3…),在索引中依次按照col1, col2, col3排序。如(1, 2), (1, 3),(2,0)…

     

             使用復(fù)合索引要充分利用最左前綴原則,顧名思義,就是最左優(yōu)先。如創(chuàng)建索引ind_col1_col2(col1, col2),那么在查詢where col1 = xxx and col2 = xx或者where col1 = xxx都可以走ind_col1_col2索引。

    在創(chuàng)建多列索引時,要根據(jù)業(yè)務(wù)需求,where子句中使用最頻繁且過濾效果好的的一列放在最左邊。

    索引操作

             可以通過DML語句操作innodb索引。因?yàn)?/span>innodb是索引組織的表,對索引的操作會造成鎖表,先生成一張臨時表,將數(shù)據(jù)從原始表中寫到臨時表,再將原始表刪除,最后將臨時表表名改為原始表表名!因增加、刪除、修改字段會對主索引產(chǎn)生影響,所以也會鎖表。對secondary indexInnodb plugin開始,支持快速索引創(chuàng)建的方法,在創(chuàng)建的過程中不需要重建表,所以速度會很快,同時引擎會在表上加S鎖,在創(chuàng)建過程中只能進(jìn)行讀操作。

    索引設(shè)計(jì)原則

    1.       搜索的索引列,不一定是所要選擇的列。也就是說,最適合索引的列是出現(xiàn)在where子句中的列,或者連接子句中指定的列,而不是出現(xiàn)在select關(guān)鍵字后的選擇列表中的列。

    2.       使用唯一索引。考慮某列的分布,索引的列的基數(shù)越大,索引的效果越好。例如,對性別M/F列做索引沒多大用處。

    3.       使用短索引。如果是對字符串進(jìn)行索引,如果有可能應(yīng)該指定前綴長度。

    4.       利用最左前綴。盡量將使用頻繁且過濾效果好的字段放“左邊”

    5.       不要過度索引。

    6.       Innodb默認(rèn)會按照一定的順序保存數(shù)據(jù),如果明確定義了主鍵,則按照主鍵順序保存。如果沒有主鍵,但有唯一索引,就按照唯一索引的順序保存。如果有幾個列都是唯一的,都可以作為主鍵的時候,為了提高查詢效率,應(yīng)選擇最常用訪問的列作為主鍵。另外,innodbsecondary index都會保存主鍵的鍵值,所有主鍵要盡可能選擇較短的數(shù)據(jù)類型。可以看出,應(yīng)當(dāng)盡量避免對主鍵的修改。經(jīng)過dba的測試,保證主鍵的遞增可以提高插入性能。

     

    Mysql如何使用索引

    1.       對于創(chuàng)建的多列索引,只要查詢的條件中用到了最左邊的列,索引一般就會被使用。

    2.       對于使用like的查詢,后面如果是常量并且只有%號不在第一個字符,索引才可能被使用。

    3.       如果對大文本進(jìn)行搜索,應(yīng)該使用全文索引,而不是使用like ‘%...%’. 但不幸的是innodb不支持全文索引。

    4.       如果列名是索引,使用 index_column is null將使用索引。Oracle是不行的。

    5.       如果mysql估計(jì)使用索引比全表掃描更慢,最不會使用索引。

    6.       如果使用memory/head表并且where條件中不使用”=”進(jìn)行索引列,那么不會用到索引。Head表只有在”=”的時候才會使用索引。

    7.       or分割開的條件,如果or前的條件中的列有索引,而后面列中沒有索引,那么涉及到的索引都不會被用到。

    8.       不是多列索引的第一部分不會走索引。

    9.       %開始的like不會走索引

    10.   如果列是字符串,那么一定要在where條件中把字符串常量值用引號引起來,否則不能走索引。因?yàn)椋?/span>mysql默認(rèn)把輸入的常量值進(jìn)行轉(zhuǎn)換以后才進(jìn)行檢索。

    11.   經(jīng)過普通運(yùn)算或函數(shù)運(yùn)算后的索引字段不能使用索引

    12.   不等于操作不能使用索,<>not in

    13.   Order by 優(yōu)化:某些情況下,mysql可以使用一個索引滿足order by,而不需要額外的排序。Where條件與order by 使用相同的索引,并且order by的順序和索引順序相同,并且order by的字段都是升序或者都是降序。

    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

    --order by 的字段混合 ASC DESC

    SELECT * FROM t1 WHERE key2=constant ORDER BY key1

    -- 用于查詢行的關(guān)鍵字與 ORDER BY 中所使用的不相同

    SELECT * FROM t1 ORDER BY key1, key2

    -- 對不同的關(guān)鍵字使用 ORDER BY     

     

    可以使用explain查看sql的執(zhí)行計(jì)劃。

    posted @ 2011-12-17 16:36 happyenjoylife 閱讀(10248) | 評論 (2)編輯 收藏
    原文:
    http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html

    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 class SampleOne {
    public static class A<T> {
    public T getT() {
    return null;
    }
    }

    public static class  B extends A<String> {
    public String getT() {
    return null;
    }
    }
    }

    Which in reality is just an example of covariant return type and after erasure will look like following snippet:

    public class SampleOne {
    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 class SampleOne$B extends SampleOne$A {
    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() {
    }

    }

    }
    If you will decompile class C, you will see method "foo" there, which overrides method from base class and delegates to it:
    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());
    Normal invocation, without using reflection, will work fine.

    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.
    posted @ 2011-08-20 10:19 happyenjoylife 閱讀(441) | 評論 (0)編輯 收藏

    異常表

    每一個try語句塊catch的異常都與異常表中的一項(xiàng)相對應(yīng),異常表中的每一項(xiàng)都包括:

    1. 起點(diǎn)
    2. 終點(diǎn),始終把catch異常位置的pc指針偏移量的最大值大1
    3.  處理異常時跳轉(zhuǎn)到的字節(jié)碼序列中的pc指針偏移量
    4.  catch的異常類的常量池索引

     

    例如:

    public class Test {
        
    public static void main(String[] args) {

            
    try {
                Class.forName(
    "java.lang.String");
            }
     catch (ClassNotFoundException e) {
                e.printStackTrace();
            }


        }

    }

    javap –c查看字節(jié)碼如下:

     

    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
    }

     

    可見ClassNotFoundException異常可能會在0~6之間拋出,9開始處的代碼處理此異常。

     

    當(dāng)產(chǎn)生異常的時候,jvm將會在整個異常表中搜索與之匹配的項(xiàng),如果當(dāng)前pc在異常表入口所指的范圍內(nèi),并且所拋出的異常是此入口所指向的類或者其子類,則跳轉(zhuǎn)到對應(yīng)的處理代碼繼續(xù)執(zhí)行。

     

    方法可能會拋出哪些已檢查異常

    Class文件的attribute_info中保存有Exceptions屬性,記錄著每個方法throws的異常信息。具體的可以查看class類文件格式相關(guān)的文章。

     

    athrow指令從棧頂彈出Throwable對象引用,拋出異常。

     

    finally語句

    jvm規(guī)范中,finally語句是通過jsr/jsr_wret指令實(shí)現(xiàn)的。當(dāng)執(zhí)行jsr/jsr_w的時候?qū)?/span>finally執(zhí)行完成后的返回地址壓入棧中,進(jìn)入finally后會馬上將此地址保存到一個局部變量中,執(zhí)行完成后,ret從此局部變量中取出返回地址。???為什么會先把返回地址保存到局部變量中呢???因?yàn)椋?dāng)從finally語句返回的時候需要將返回地址成棧中彈出,當(dāng)finally語句非正常結(jié)束(break,continue,return, 拋異常)的時候就不用再考慮這個問題。

     

    以下是jvm規(guī)范中Compiling 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

     

    當(dāng)tryItOut排除任何異常后都將會被異常表中的any項(xiàng)捕獲,執(zhí)行完finally后,會執(zhí)行athrow指令將異常拋出。

     

    jdk的某一個版本開始就不會編譯出編譯出含jsr/jsr_wret的字節(jié)碼了,因?yàn)橛兄噶钌系娜毕荩瑢?dǎo)致jvm的檢驗(yàn)和分析系統(tǒng)出現(xiàn)漏洞。

     

    再說finally的非正常退出

    finally中使用breakcontinuereturn、拋出異常等認(rèn)為是finally的非正常結(jié)束。非正常結(jié)束的時候,ret指令不會被執(zhí)行,很可能會出現(xiàn)意想不到的結(jié)果。如:

     

    public class Test {
        
    public static boolean test(boolean b) {
            
    while (b) {
                
    try {
                    
    return true;
                }
     finally {
                    
    /*
                    break;                          始終返回false
                    continue;                         javac編譯再java執(zhí)行會出現(xiàn)死循環(huán)
                                                    在eclipse中甚至?xí)霈F(xiàn)報錯:提示找到不main class
                    return false;                     始終返回false
                    throw new RuntimeException("");    拋出異常
                     
    */

                }

            }


            
    return false;
        }


        
    public static void main(String[] args) {
            System.out.println(test(
    true));
        }

    }


    建議:在寫finally語句的時候,盡量避免非正常結(jié)束!


     

    posted @ 2011-05-27 14:39 happyenjoylife 閱讀(2596) | 評論 (4)編輯 收藏

    導(dǎo)航

    <2011年5月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    統(tǒng)計(jì)

    常用鏈接

    留言簿

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久久久久久综合日本亚洲| 国产美女无遮挡免费视频网站 | 中文字幕视频在线免费观看| 亚洲Av无码专区国产乱码DVD| 97在线线免费观看视频在线观看| 老司机亚洲精品影院在线观看| 亚洲日本中文字幕一区二区三区| 免费无遮挡无码永久视频| 亚洲熟妇无码AV| 亚洲人成人无码网www电影首页| 91网站免费观看| 九九久久国产精品免费热6| 久久久久亚洲AV无码专区体验| 好男人视频社区精品免费| 中文字幕的电影免费网站| 亚洲色偷偷色噜噜狠狠99| 亚洲熟妇少妇任你躁在线观看| 亚洲av无码片vr一区二区三区| 亚洲人成在线影院| 在线观看午夜亚洲一区| 国产在线国偷精品产拍免费| 国产成人精品无码免费看| 亚洲第一se情网站| 一级美国片免费看| 三级黄色免费观看| 6080午夜一级毛片免费看| 91免费国产视频| 99久久99久久精品免费观看 | 中文字幕高清免费不卡视频| 成人性做爰aaa片免费看| 少妇亚洲免费精品| 亚洲av中文无码乱人伦在线观看| 亚洲免费网站在线观看| 亚洲av无码不卡| 亚洲一卡二卡三卡| 亚洲美女aⅴ久久久91| 亚洲av综合av一区| 亚洲国产成人精品电影| 精品韩国亚洲av无码不卡区| 国产午夜无码片免费| 4hu四虎最新免费地址|