MySQL索引底層實現原理

索引的本質

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。提取句子主干,就可以得到索引的本質:索引是數據結構。

我們知道,數據庫查詢是數據庫的最主要功能之一。我們都希望查詢數據的速度能盡可能的快,因此數據庫系統的設計者會從查詢算法的角度進行優化。最基本的查詢算法當然是順序查找(linear search),這種復雜度為O(n)的算法在數據量很大時顯然是糟糕的,好在計算機科學的發展提供了很多更優秀的查找算法,例如二分查找(binary search)、二叉樹查找(binary tree search)等。如果稍微分析一下會發現,每種查找算法都只能應用于特定的數據結構之上,例如二分查找要求被檢索數據有序,而二叉樹查找只能應用于二叉查找樹上,但是數據本身的組織結構不可能完全滿足各種數據結構(例如,理論上不可能同時將兩列都按順序進行組織),所以,在數據之外,數據庫系統還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

看一個例子:
image.png-32.8kB

上圖展示了一種可能的索引方式。左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址(注意邏輯上相鄰的記錄在磁盤上也并不是一定物理相鄰的)。為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在O(logn2)O(log2n)的復雜度內獲取到相應數據。

雖然這是一個貨真價實的索引,但是實際的數據庫系統幾乎沒有使用二叉查找樹或其進化品種紅黑樹(red-black tree)實現的,原因會在下文介紹。

二叉排序樹

在介紹B樹之前,先來看另一棵神奇的樹——二叉排序樹(Binary Sort Tree),首先它是一棵樹,“二叉”這個描述已經很明顯了,就是樹上的一根樹枝開兩個叉,于是遞歸下來就是二叉樹了(下圖所示),而這棵樹上的節點是已經排好序的,具體的排序規則如下:

  • 若左子樹不空,則左子樹上所有節點的值均小于它的根節點的值
  • 若右子樹不空,則右字數上所有節點的值均大于它的根節點的值
  • 它的左、右子樹也分別為二叉排序數(遞歸定義)

從圖中可以看出,二叉排序樹組織數據時,用于查找是比較方便的,因為每次經過一次節點時,最多可以減少一半的可能,不過極端情況會出現所有節點都位于同一側,直觀上看就是一條直線,那么這種查詢的效率就比較低了,因此需要對二叉樹左右子樹的高度進行平衡化處理,于是就有了平衡二叉樹(Balenced Binary Tree)。

所謂“平衡”,說的是這棵樹的各個分支的高度是均勻的,它的左子樹和右子樹的高度之差絕對值小于1,這樣就不會出現一條支路特別長的情況。于是,在這樣的平衡樹中進行查找時,總共比較節點的次數不超過樹的高度,這就確保了查詢的效率(時間復雜度為O(logn))

B樹

還是直接看圖比較清楚,圖中所示,B樹事實上是一種平衡的多叉查找樹,也就是說最多可以開m個叉(m>=2),我們稱之為m階b樹,為了體現本博客的良心之處,不同于其他地方都能看到2階B樹,這里特意畫了一棵5階B樹 。

總的來說,m階B樹滿足以下條件:

  • 每個節點至多可以擁有m棵子樹。
  • 根節點,只有至少有2個節點(要么極端情況,就是一棵樹就一個根節點,單細胞生物,即是根,也是葉,也是樹)。
  • 非根非葉的節點至少有的Ceil(m/2)個子樹(Ceil表示向上取整,圖中5階B樹,每個節點至少有3個子樹,也就是至少有3個叉)。
  • 非葉節點中的信息包括[n,A0,K1,A1,K2,A2,…,Kn,An],,其中n表示該節點中保存的關鍵字個數,K為關鍵字且Ki<Ki+1,A為指向子樹根節點的指針。
  • 從根到葉子的每一條路徑都有相同的長度,也就是說,葉子節在相同的層,并且這些節點不帶信息,實際上這些節點就表示找不到指定的值,也就是指向這些節點的指針為空。

B樹的查詢過程和二叉排序樹比較類似,從根節點依次比較每個結點,因為每個節點中的關鍵字和左右子樹都是有序的,所以只要比較節點中的關鍵字,或者沿著指針就能很快地找到指定的關鍵字,如果查找失敗,則會返回葉子節點,即空指針。

例如查詢圖中字母表中的K:

  1. 從根節點P開始,K的位置在P之前,進入左側指針。
  2. 左子樹中,依次比較C、F、J、M,發現K在J和M之間。
  3. 沿著J和M之間的指針,繼續訪問子樹,并依次進行比較,發現第一個關鍵字K即為指定查找的值。

B樹搜索的簡單偽算法如下:

BTree_Search(node, key) {if(node == null) return null; foreach(node.key) { if(node.key[i] == key) return node.data[i]; if(node.key[i] > key) return BTree_Search(point[i]->node); } return BTree_Search(point[i+1]->node); } data = BTree_Search(root, my_key);

B樹的特點可以總結為如下:

  1. 關鍵字集合分布在整顆樹中。
  2. 任何一個關鍵字出現且只出現在一個節點中。
  3. 搜索有可能在非葉子節點結束。
  4. 其搜索性能等價于在關鍵字集合內做一次二分查找。
  5. B樹在插入刪除新的數據記錄會破壞B-Tree的性質,因為在插入刪除時,需要對樹進行一個分裂、合并、轉移等操作以保持B-Tree性質。

Plus版 — B+樹

作為B樹的加強版,B+樹與B樹的差異在于

  • 有n棵子樹的節點含有n個關鍵字(也有認為是n-1個關鍵字)。
  • 所有的關鍵字全部存儲在葉子節點上,且葉子節點本身根據關鍵字自小而大順序連接。
  • 非葉子節點可以看成索引部分,節點中僅含有其子樹(根節點)中的最大(或最小)關鍵字。

B+樹的查找過程,與B樹類似,只不過查找時,如果在非葉子節點上的關鍵字等于給定值,并不終止,而是繼續沿著指針直到葉子節點位置。因此在B+樹,不管查找成功與否,每次查找都是走了一條從根到葉子節點的路徑。

B+樹的特性如下:

  • 所有關鍵字都存儲在葉子節上,且鏈表中的關鍵字恰好是有序的。
  • 不可能非葉子節點命中返回。
  • 非葉子節點相當于葉子節點的索引,葉子節點相當于是存儲(關鍵字)數據的數據層。
  • 更適合文件索引系統。

帶有順序訪問指針的B+Tree

一般在數據庫系統或文件系統中使用的B+Tree結構都在經典B+Tree的基礎上進行了優化,增加了順序訪問指針。

如上圖所示,在B+Tree的每個葉子節點增加一個指向相鄰葉子節點的指針,就形成了帶有順序訪問指針的B+Tree。做這個優化的目的是為了提高區間訪問的性能,例如圖4中如果要查詢key為從18到49的所有數據記錄,當找到18后,只需順著節點和指針順序遍歷就可以一次性訪問到所有數據節點,極大提到了區間查詢效率。

MySQL為什么使用B樹(B+樹)

紅黑樹等數據結構也可以用來實現索引,但是文件系統以及數據庫系統普遍采用B樹或者B+樹,這一節將結合計算機組成原理相關知識討論B-/+Tree作為索引的理論基礎。

一般來說,索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。這樣的話,索引查找過程中就要產生磁盤I/O消耗,相對于內存存取,I/O存取的消耗要高幾個數量級,所以評價一個數據結構作為索引的優劣最重要的指標就是在查找過程中磁盤I/O操作次數的漸進復雜度。換句話說,索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數。下面先介紹內存和磁盤存取原理,然后再結合這些原理分析B-/+Tree作為索引的效率。

主存存取原理

目前計算機使用的主存基本都是隨機讀寫存儲器(RAM),現代RAM的結構和存取原理比較復雜,這里本文拋卻具體差別,抽象出一個十分簡單的存取模型來說明RAM的工作原理。

從抽象角度看,主存是一系列的存儲單元組成的矩陣,每個存儲單元存儲固定大小的數據。每個存儲單元有唯一的地址,現代主存的編址規則比較復雜,這里將其簡化成一個二維地址:通過一個行地址和一個列地址可以唯一定位到一個存儲單元。上圖展示了一個4 x 4的主存模型。

主存的存取過程如下:

當系統需要讀取主存時,則將地址信號放到地址總線上傳給主存,主存讀到地址信號后,解析信號并定位到指定存儲單元,然后將此存儲單元數據放到數據總線上,供其它部件讀取。

寫主存的過程類似,系統將要寫入單元地址和數據分別放在地址總線和數據總線上,主存讀取兩個總線的內容,做相應的寫操作。

這里可以看出,主存存取的時間僅與存取次數呈線性關系,因為不存在機械操作,兩次存取的數據的“距離”不會對時間有任何影響,例如,先取A0再取A1和先取A0再取D3的時間消耗是一樣的。

磁盤存取原理

上文說過,索引一般以文件形式存儲在磁盤上,索引檢索需要磁盤I/O操作。與主存不同,磁盤I/O存在機械運動耗費,因此磁盤I/O的時間消耗是巨大的。

下圖是磁盤的整體結構示意圖:

一個磁盤由大小相同且同軸的圓形盤片組成,磁盤可以轉動(各個磁盤必須同步轉動)。在磁盤的一側有磁頭支架,磁頭支架固定了一組磁頭,每個磁頭負責存取一個磁盤的內容。磁頭不能轉動,但是可以沿磁盤半徑方向運動(實際是斜切向運動),每個磁頭同一時刻也必須是同軸的,即從正上方向下看,所有磁頭任何時候都是重疊的(不過目前已經有多磁頭獨立技術,可不受此限制)。

下圖是磁盤結構的示意圖:

盤片被劃分成一系列同心環,圓心是盤片中心,每個同心環叫做一個磁道,所有半徑相同的磁道組成一個柱面。磁道被沿半徑線劃分成一個個小的段,每個段叫做一個扇區,每個扇區是磁盤的最小存儲單元。為了簡單起見,我們下面假設磁盤只有一個盤片和一個磁頭。

當需要從磁盤讀取數據時,系統會將數據邏輯地址傳給磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即確定要讀的數據在哪個磁道,哪個扇區。為了讀取這個扇區的數據,需要將磁頭放到這個扇區上方,為了實現這一點,磁頭需要移動對準相應磁道,這個過程叫做尋道,所耗費時間叫做尋道時間,然后磁盤旋轉將目標扇區旋轉到磁頭下,這個過程耗費的時間叫做旋轉時間。

局部性原理與磁盤預讀

由于存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分分之一,因此為了提高效率,要盡量減少磁盤I/O。為了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向后讀取一定長度的數據放入內存。這樣做的理論依據是計算機科學中著名的局部性原理:

當一個數據被用到時,其附近的數據也通常會馬上被使用。

所以,程序運行期間所需要的數據通常應當比較集中。

由于磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對于具有局部性的程序來說,預讀可以提高I/O效率。

預讀的長度一般為頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操作系統往往將主存和磁盤存儲區分割為連續的大小相等的塊,每個存儲塊稱為一頁(在許多操作系統中,頁得大小通常為4k),主存和磁盤以頁為單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置并向后連續讀取一頁或幾頁載入內存中,然后異常返回,程序繼續運行。

B-/+Tree索引的性能分析

到這里終于可以分析B-/+Tree索引的性能了。

上文說過一般使用磁盤I/O次數評價索引結構的優劣。先從B-Tree分析,根據B-Tree的定義,可知檢索一次最多需要訪問h個節點。數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設為等于一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B-Tree還需要使用如下技巧:

每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。

B-Tree中一次檢索最多需要h-1次I/O(根節點常駐內存),漸進復雜度為O(h)=O(logdN)O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小(通常不超過3)。(h表示樹的高度 & 出度d表示的是樹的度,即樹中各個節點的度的最大值)

綜上所述,用B-Tree作為索引結構效率是非常高的。

而紅黑樹這種結構,h明顯要深的多。由于邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的I/O漸進復雜度也為O(h),效率明顯比B-Tree差很多。

上文還說過,B+Tree更適合外存索引,原因和內節點出度d有關。從上面分析可以看到,d越大索引的性能越好,而出度的上限取決于節點內key和data的大小:

?

dmax=floor(pagesize/(keysize+datasize+pointsize))dmax=floor(pagesize/(keysize+datasize+pointsize))

?

floor表示向下取整。由于B+Tree內節點去掉了data域,因此可以擁有更大的出度,擁有更好的性能。

MySQL索引實現

在MySQL中,索引屬于存儲引擎級別的概念,不同存儲引擎對索引的實現方式是不同的,本文主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式。

MyISAM索引實現

MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖:

這里設表一共有三列,假設我們以Col1為主鍵,則上圖是一個MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件僅僅保存數據記錄的地址。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:

同樣也是一棵B+樹,data域保存數據記錄的地址。因此,MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,讀取相應數據記錄。

MyISAM的索引方式也叫做“非聚集”的,之所以這么稱呼是為了與InnoDB的聚集索引區分。

InnoDB索引實現

雖然InnoDB也使用B+Tree作為索引結構,但具體實現方式卻與MyISAM截然不同。

第一個重大區別是InnoDB的數據文件本身就是索引文件。從上文知道,MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

上圖是InnoDB主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節,類型為長整型。

第二個與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。例如,上圖為定義在Col3上的一個輔助索引:

這里以英文字符的ASCII碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

了解不同存儲引擎的索引實現方式對于正確使用和優化索引都非常有幫助,例如知道了InnoDB的索引實現后,就很容易明白為什么不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段作為主鍵在InnoDB中不是個好主意,因為InnoDB數據文件本身是一棵B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。

轉載于:https://www.cnblogs.com/liuyaofei/p/9989235.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450210.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450210.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450210.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決 A component required a bean of ‘XXX.RoleService‘ that could not be found.

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 springboot工程啟動報錯&#xff0c;無法啟動成功。 dubbo訂閱服務失敗&#xff0c;提示如下&#xff1a; 出錯原因&#xff1a;唉&…

開源個小工具simple-repo

背景 了解android系統的都應該熟悉repo這個工具&#xff0c;google為了方便管理數百個git倉庫&#xff0c;開發了repo這個批量管理工具。不過google repo project配置比較麻煩&#xff0c;而通過gitbucket搭建git server則比較傻瓜&#xff0c;所以此處開發了simple-repo這么一…

配合OAuth2進行單設備登錄攔截

2019獨角獸企業重金招聘Python工程師標準>>> 要進行單設備登錄&#xff0c;在其他地點登錄后&#xff0c;本地的其他操作會被攔截返回登錄界面。 原理就在于要在登錄時在redis中存儲Session,進行操作時要進行Session的比對。 具體實現&#xff0c;假設我們的OAuth 2…

朱大鳴:中國金融危機到底有多嚴重

我們到底該不該救助金融機構&#xff0c;中國鈔票到底有沒有超發&#xff0c;對于這個問題&#xff0c;央行行長周小川日前撰文全面為之辯護&#xff1a;對于第一個問題&#xff0c;他的觀點是金融業出現了問題就必須救&#xff0c;否則意味著集體的失靈甚至死亡&#xff1b;中…

C++知識點(六)數組、指針與字符串導學

1.數組 地址連續存放初始化&#xff1a;列出全部初始值后&#xff0c;第1維下標個數可以省略不做初始化&#xff0c;局部變量中為垃圾數據&#xff0c;static變量為0只對一部分進行初始化&#xff0c;其余數值初始化為02.動態內存分配&#xff1a; new delete 3.動態創建數組 n…

Android應用開發—知識點匯總

獲取Fragment的context&#xff1a; getActivity().getApplicationContext()或者getActivity()You can use getActivity(), which returns the activity associated with a fragment.The activity is a context (since Activity extends Context).設置TextView的顏色setTextCol…

條件渲染vue

v-if:只渲染一次的情況下&#xff0c;性能更好v-show:頻繁切換性能更好 vue虛擬DOM技術 瀏覽器&#xff1a;渲染引擎&#xff08;慢&#xff09;JS引擎&#xff08;快&#xff09; 用1個JS對象來充當DOM對象&#xff0c;因為JS對象性能比較快&#xff0c;所以用虛擬DOM對象進行…

錢線觀察:貨幣基金T+0駕到 活期存款將死?

導語&#xff1a;即使沒有任何投資風險&#xff0c;通脹也在侵蝕居民的財富&#xff0c;現金是不安全的。最近出現的一項業務&#xff0c;貨幣基金"T0"贖回&#xff0c;意味著貨幣基金可以像活期存款一樣即時取現&#xff0c;而其收益率普遍高于活期存款。因此有人認…

git stash和git stash pop

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 git stash 可用來暫存當前正在進行的工作&#xff0c; 比如想pull 最新代碼&#xff0c; 又不想加新commit&#xff0c; 或者另外一種情…

CentOS 7.0 上安裝和配置 VNC 服務器

作為一個系統管理員&#xff0c;大多數時間是通過網絡管理服務器的。在管理服務器的過程中很少會用到圖形界面&#xff0c;多數情況下我們只是用 SSH 來完成我們的管理任務。在這篇文章里&#xff0c;我們將配置 VNC 來提供一個連接我們 CentOS 7 服務器的方法。VNC 允許我們開…

Android應用開發—TextView的動態創建

動態創建TextView的兩種方式&#xff1a; 下面介紹兩種創建方式&#xff1a; 在drawable里面創建共同依賴的background.xml文件&#xff0c;里面設置shape來設置文本框的一些特殊效果&#xff1a; eg&#xff1a; <?xml version"1.0" encoding"utf-8"…

Mongo DB 簡單搭建和部署

1.先下載源代碼包 官網下載地址&#xff1a;http://www.mongodb.org/downloads 2.解包tar xf mongodb-linux-x86_64-rhel62-3.2.7.tgz 3.把包移動到 /usr/local/mongodb mv mongodb-linux-x86_64-rhel62-3.2.7/ /usr/local/mongodb 指定同一時間最多可開啟的文件數&#xff08…

運算符優先級 必熟記,放到心里

優先級 運算符 名稱或含義 使用形式 結合方向 說明 1 [] 數組下標 數組名[常量表達式] 左到右 () 圓括號 &#xff08;表達式&#xff09;/函數名(形參表) . 成員選擇&#xff08;對象&#xff09; 對象.成員名 -> 成員選擇&#xff08;指針&#xff0…

可持久化平衡樹(FHQ Treap)

兩個最基本的操作 merge合并 split分割 merge 把兩棵treap合并成一棵treap&#xff0c;要滿足T1最大值要比T2最小值小&#xff0c;比較將隨機數值key值更大的作為合并后的根 假設T1作為根節點作為新子樹的根&#xff0c;左子樹不變&#xff0c;右子樹對T1原來的右子樹與T2再遞歸…

Git 分支管理-git stash 和git stash pop

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 合并分支&#xff0c;沖突是難免的&#xff0c;在實際協作開發中我們遇到的情況錯綜復雜&#xff0c;今天就講兩個比較重要的命令使用gi…

useState語法講解

useState語法講解 語法定義 const [state, dispatch] useState(initData)state&#xff1a;定義的數據源&#xff0c;可視作一個函數組件內部的變量&#xff0c;但只在首次渲染被創造。dispatch&#xff1a;改變state的函數&#xff0c;推動函數渲染的渲染函數。dispatch有兩…

NSOperation的進階使用和簡單探討

本文將會從多個方面探討NSOperation類和NSOperationQueue類的相關內容 一、簡介 NSOperation類是iOS2.0推出的&#xff0c;通過NSThread實現的,但是效率一般。 從OS X10.6和iOS4推出GCD時&#xff0c;又重寫了NSOperation和NSOperationQueue&#xff0c;NSOperation和NSOperati…

Android應用開發—LayoutParams的用法

Android應用開發—TextView的動態創建 這篇文章講到了“TextView控件布局位置的控制”&#xff0c;主要依賴于RelativeLayout.LayoutParams的使用&#xff0c;本文簡單介紹下LayoutParams的用法 注&#xff1a;本文大部分內容參考android,利用layoutParams代碼動態布局空間位置…

廖雪峰Java1-2程序基礎-7布爾運算符

布爾運算符 關系運算符&#xff1a;>&#xff0c; >&#xff0c; <&#xff0c; <&#xff0c; &#xff0c;!與運算 &&或運算 |非運算 &#xff01;int n 5;boolean t n > 0;//trueboolean f n < 0;//falseboolean isFive n 5;//trueboolean i…