當前位置:首頁 » 編程語言 » 建立聯合索引的sql
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

建立聯合索引的sql

發布時間: 2023-04-05 06:02:38

⑴ mysql怎麼添加索引sql語句

工具:mysql資料庫創建一個user的表裡邊的欄位
1.普通索引 添加INDEX
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )

下面演示下給user表的name欄位添加一個索引

2.主鍵索引 添加PRIMARY KEY
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )

3.唯一索引 添加UNIQUE
ALTER TABLE `table_name` ADD UNIQUE ( `column` )

4.全文索引 添加FULLTEXT
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)

5.如何添加多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

⑵ mysql 核心內容-上

1、SQL語句執行流程

MySQL大體上可分為Server層和存儲引擎層兩部分。

Server層:

連接器:TCP握手後伺服器來驗證登陸用戶身份,A用戶創建連接後,管理員對A用戶許可權修改了也不會影響到已經創建的鏈接許可權,必須重新登陸。

查詢緩存:查詢後的結果存儲位置,MySQL8.0版本以後已經取消,因為查詢緩存失效太頻繁,得不償失。

分析器:根據語法規則,判斷你輸入的這個SQL語句是否滿足MySQL語法。

優化器:多種執行策略可實現目標,系統自動選擇最優進行執行。

執行器:判斷是否有許可權,將最終任務提交到存儲引擎。

存儲引擎層

負責數據的存儲和提取。其架構模式是插件式的,支持InnoDB、MyISAM、Memory等多個存儲引擎。現在最常用的存儲引擎是InnoDB,它從MySQL 5.5.5版本開始成為了默認存儲引擎(經常用的也是這個)。

SQL執行順序

2、BinLog、RedoLog、UndoLog

BinLog

BinLog是記錄所有資料庫表結構變更(例如create、alter table)以及表數據修改(insert、update、delete)的二進制日誌,主從資料庫同步用到的都是BinLog文件。BinLog日誌文件有三種模式。

STATEMENT 模式

內容:binlog 記錄可能引起數據變更的 sql 語句

優勢:該模式下,因為沒有記錄實際的數據,所以日誌量很少 IO 都消耗很低,性能是最優的

劣勢:但有些操作並不是確定的,比如 uuid() 函數會隨機產生唯一標識,當依賴 binlog 回放時,該操作生成的數據與原數據必然是不同的,此時可能造成無法預料的後果。

ROW 模式

內容:在該模式下,binlog 會記錄每次操作的源數據與修改後的目標數據,StreamSets就要求該模式。

優勢:可以絕對精準的還原,從而保證了數據的安全與可靠,並且復制和數據恢復過程可以是並發進行的

劣勢:缺點在於 binlog 體積會非常大,同時,對於修改記錄多、欄位長度大的操作來說,記錄時性能消耗會很嚴重。閱讀的時候也需要特殊指令來進行讀取數據。

MIXED 模式

內容:是對上述STATEMENT 跟 ROW 兩種模式的混合使用。

細節:對於絕大部分操作,都是使用 STATEMENT 來進行 binlog 沒有記錄,只有以下操作使用 ROW 來實現:表的存儲引擎為 NDB,使用了uuid() 等不確定函數,使用了 insert delay 語句,使用了臨時表

主從同步流程:

1、主節點必須啟用二進制日誌,記錄任何修改了資料庫數據的事件。

2、從節點開啟一個線程(I/O Thread)把自己扮演成 mysql 的客戶端,通過 mysql 協議,請求主節點的二進制日誌文件中的事件 。

3、主節點啟動一個線程(mp Thread),檢查自己二進制日誌中的事件,跟對方請求的位置對比,如果不帶請求位置參數,則主節點就會從第一個日誌文件中的第一個事件一個一個發送給從節點。

4、從節點接收到主節點發送過來的數據把它放置到中繼日誌(Relay log)文件中。並記錄該次請求到主節點的具體哪一個二進制日誌文件內部的哪一個位置(主節點中的二進制文件會有多個)。

5、從節點啟動另外一個線程(sql Thread ),把 Relay log 中的事件讀取出來,並在本地再執行一次。

mysql默認的復制方式是非同步的,並且復制的時候是有並行復制能力的。主庫把日誌發送給從庫後不管了,這樣會產生一個問題就是假設主庫掛了,從庫處理失敗了,這時候從庫升為主庫後,日誌就丟失了。由此產生兩個概念。

全同步復制

主庫寫入binlog後強制同步日誌到從庫,所有的從庫都執行完成後才返回給客戶端,但是很顯然這個方式的話性能會受到嚴重影響。

半同步復制

半同步復制的邏輯是這樣,從庫寫入日誌成功後返回ACK確認給主庫,主庫收到至少一個從庫的確認就認為寫操作完成。

還可以延伸到由於主從配置不一樣、主庫大事務、從庫壓力過大、網路震盪等造成主備延遲,如何避免這個問題?主備切換的時候用可靠性優先原則還是可用性優先原則?如何判斷主庫Crash了?互為主備的情況下如何避免主備循環復制?被刪庫跑路了如何正確恢復?( o )… 感覺越來越扯到DBA的活兒上去了。

RedoLog

可以先通過下面demo理解:

飯點記賬可以把賬單寫在賬本上也可以寫在粉板上。有人賒賬或者還賬的話,一般有兩種做法:

1、直接把賬本翻出來,把這次賒的賬加上去或者扣除掉。

2、先在粉板上記下這次的賬,等打烊以後再把賬本翻出來核算。

生意忙時選後者,因為前者太麻煩了。得在密密麻麻的記錄中找到這個人的賒賬總額信息,找到之後再拿出算盤計算,最後再將結果寫回到賬本上。

同樣在MySQL中如果每一次的更新操作都需要寫進磁碟,然後磁碟也要找到對應的那條記錄,然後再更新,整個過程IO成本、查找成本都很高。而粉板和賬本配合的整個過程就是MySQL用到的是Write-Ahead Logging 技術,它的關鍵點就是先寫日誌,再寫磁碟。此時賬本 = BinLog,粉板 = RedoLog。

1、 記錄更新時,InnoDB引擎就會先把記錄寫到RedoLog(粉板)裡面,並更新內存。同時,InnoDB引擎會在空閑時將這個操作記錄更新到磁碟裡面。

2、 如果更新太多RedoLog處理不了的時候,需先將RedoLog部分數據寫到磁碟,然後擦除RedoLog部分數據。RedoLog類似轉盤。

RedoLog有write pos 跟checkpoint

write pos :是當前記錄的位置,一邊寫一邊後移,寫到第3號文件末尾後就回到0號文件開頭。

check point:是當前要擦除的位置,也是往後推移並且循環的,擦除記錄前要把記錄更新到數據文件。

write pos和check point之間的是粉板上還空著的部分,可以用來記錄新的操作。如果write pos追上checkpoint,表示粉板滿了,這時候不能再執行新的更新,得停下來先擦掉一些記錄,把checkpoint推進一下。

有了redo log,InnoDB就可以保證即使資料庫發生異常重啟,之前提交的記錄都不會丟失,這個能力稱為crash-safe。 redolog兩階段提交:為了讓binlog跟redolog兩份日誌之間的邏輯一致。提交流程大致如下:

1 prepare階段 --> 2 寫binlog --> 3 commit

當在2之前崩潰時,重啟恢復後發現沒有commit,回滾。備份恢復:沒有binlog 。一致

當在3之前崩潰時,重啟恢復發現雖沒有commit,但滿足prepare和binlog完整,所以重啟後會自動commit。備份:有binlog. 一致

binlog跟redolog區別:

redo log是InnoDB引擎特有的;binlog是MySQL的Server層實現的,所有引擎都可以使用。

redo log是物理日誌,記錄的是在某個數據頁上做了什麼修改;binlog是邏輯日誌,記錄的是這個語句的原始邏輯,比如給ID=2這一行的c欄位加1。

redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的。追加寫是指binlog文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。

UndoLog

UndoLog 一般是邏輯日誌,主要分為兩種:

insert undo log

代表事務在insert新記錄時產生的undo log, 只在事務回滾時需要,並且在事務提交後可以被立即丟棄

update undo log

事務在進行update或delete時產生的undo log; 不僅在事務回滾時需要,在快照讀時也需要;所以不能隨便刪除,只有在快速讀或事務回滾不涉及該日誌時,對應的日誌才會被purge線程統一清除

3、MySQL中的索引

索引的常見模型有哈希表、有序數組和搜索樹。

哈希表:一種以KV存儲數據的結構,只適合等值查詢,不適合范圍查詢。

有序數組:只適用於靜態存儲引擎,涉及到插入的時候比較麻煩。可以參考Java中的ArrayList。

搜索樹:按照數據結構中的二叉樹來存儲數據,不過此時是N叉樹(B+樹)。廣泛應用在存儲引擎層中。

B+樹比B樹優勢在於:

B+ 樹非葉子節點存儲的只是索引,可以存儲的更多。B+樹比B樹更加矮胖,IO次數更少。

B+ 樹葉子節點前後管理,更加方便范圍查詢。同時結果都在葉子節點,查詢效率穩定。

B+樹中更有利於對數據掃描,可以避免B樹的回溯掃描。

索引的優點:

1、唯一索引可以保證每一行數據的唯一性

2、提高查詢速度

3、加速表與表的連接

4、顯著的減少查詢中分組和排序的時間

5、通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

索引的缺點:

1、創建跟維護都需要耗時

2、創建索引時,需要對表加鎖,在鎖表的同時,可能會影響到其他的數據操作

3、 索引需要磁碟的空間進行存儲,磁碟佔用也很快。

4、當對表中的數據進行CRUD的時,也會觸發索引的維護,而維護索引需要時間,可能會降低數據操作性能

索引設計的原則不應該:

1、索引不是越多越好。索引太多,維護索引需要時間跟空間。

2、 頻繁更新的數據,不宜建索引。

3、數據量小的表沒必要建立索引。

應該:

1、重復率小的列建議生成索引。因為重復數據少,索引樹查詢更有效率,等價基數越大越好。

2、數據具有唯一性,建議生成唯一性索引。在資料庫的層面,保證數據正確性

3、頻繁group by、order by的列建議生成索引。可以大幅提高分組和排序效率

4、經常用於查詢條件的欄位建議生成索引。通過索引查詢,速度更快

索引失效的場景

1、模糊搜索:左模糊或全模糊都會導致索引失效,比如'%a'和'%a%'。但是右模糊是可以利用索引的,比如'a%' 。

2、隱式類型轉換:比如select * from t where name = xxx , name是字元串類型,但是沒有加引號,所以是由MySQL隱式轉換的,所以會讓索引失效 3、當語句中帶有or的時候:比如select * from t where name=『sw』 or age=14

4、不符合聯合索引的最左前綴匹配:(A,B,C)的聯合索引,你只where了C或B或只有B,C

關於索引的知識點:

主鍵索引:主鍵索引的葉子節點存的是整行數據信息。在InnoDB里,主鍵索引也被稱為聚簇索引(clustered index)。主鍵自增是無法保證完全自增的哦,遇到唯一鍵沖突、事務回滾等都可能導致不連續。

唯一索引:以唯一列生成的索引,該列不允許有重復值,但允許有空值(NULL)

普通索引跟唯一索引查詢性能:InnoDB的數據是按數據頁為單位來讀寫的,默認每頁16KB,因此這兩種索引查詢數據性能差別微乎其微。

change buffer:普通索引用在更新過程的加速,更新的欄位如果在緩存中,如果是普通索引則直接更新即可。如果是唯一索引需要將所有數據讀入內存來確保不違背唯一性,所以盡量用普通索引。

非主鍵索引:非主鍵索引的葉子節點內容是主鍵的值。在InnoDB里,非主鍵索引也被稱為二級索引(secondary index)

回表:先通過資料庫索引掃描出數據所在的行,再通過行主鍵id取出索引中未提供的數據,即基於非主鍵索引的查詢需要多掃描一棵索引樹。

覆蓋索引:如果一個索引包含(或者說覆蓋)所有需要查詢的欄位的值,我們就稱之為覆蓋索引。

聯合索引:相對單列索引,組合索引是用多個列組合構建的索引,一次性最多聯合16個。

最左前綴原則:對多個欄位同時建立的組合索引(有順序,ABC,ACB是完全不同的兩種聯合索引) 以聯合索引(a,b,c)為例,建立這樣的索引相當於建立了索引a、ab、abc三個索引。另外組合索引實際還是一個索引,並非真的創建了多個索引,只是產生的效果等價於產生多個索引。

索引下推:MySQL 5.6引入了索引下推優化,可以在索引遍歷過程中,對索引中包含的欄位先做判斷,過濾掉不符合條件的記錄,減少回表字數。

索引維護:B+樹為了維護索引有序性涉及到頁分裂跟頁合並。增刪數據時需考慮頁空間利用率。

自增主鍵:一般會建立與業務無關的自增主鍵,不會觸發葉子節點分裂。

延遲關聯:通過使用覆蓋索引查詢返回需要的主鍵,再根據主鍵關聯原表獲得需要的數據。

InnoDB存儲: * .frm文件是一份定義文件,也就是定義資料庫表是一張怎麼樣的表。*.ibd文件則是該表的索引,數據存儲文件,既該表的所有索引樹,所有行記錄數據都存儲在該文件中。

MyISAM存儲:* .frm文件是一份定義文件,也就是定義資料庫表是一張怎麼樣的表。* .MYD文件是MyISAM存儲引擎表的所有行數據的文件。* .MYI文件存放的是MyISAM存儲引擎表的索引相關數據的文件。MyISAM引擎下,表數據和表索引數據是分開存儲的。

MyISAM查詢:在MyISAM下,主鍵索引和輔助鍵索引都屬於非聚簇索引。查詢不管是走主鍵索引,還是非主鍵索引,在葉子結點得到的都是目的數據的地址,還需要通過該地址,才能在數據文件中找到目的數據。

PS:InnoDB支持聚簇索引,MyISAM不支持聚簇索引

4、SQL事務隔離級別

ACID的四個特性

原子性(Atomicity):把多個操作放到一個事務中,保證這些操作要麼都成功,要麼都不成功

一致性(Consistency):理解成一串對數據進行操作的程序執行下來,不會對數據產生不好的影響,比如憑空產生,或消失

隔離性(Isolation,又稱獨立性):隔離性的意思就是多個事務之間互相不幹擾,即使是並發事務的情況下,他們只是兩個並發執行沒有交集,互不影響的東西;當然實現中,也不一定需要這么完整隔離性,即不一定需要這么的互不幹擾,有時候還是允許有部分干擾的。所以MySQL可以支持4種事務隔離性

持久性(Durability):當某個操作操作完畢了,那麼結果就是這樣了,並且這個操作會持久化到日誌記錄中

PS:ACID中C與CAP定理中C的區別

ACID的C著重強調單資料庫事務操作時,要保證數據的完整和正確性,數據不會憑空消失跟增加。CAP 理論中的C指的是對一個數據多個備份的讀寫一致性

事務操作可能會出現的數據問題

1、臟讀(dirty read):B事務更改數據還未提交,A事務已經看到並且用了。B事務如果回滾,則A事務做錯了

2、 不可重復讀(non-repeatable read):不可重復讀的重點是修改: 同樣的條件, 你讀取過的數據, 再次讀取出來發現值不一樣了,只需要鎖住滿足條件的記錄

3、 幻讀(phantom read):事務A先修改了某個表的所有紀錄的狀態欄位為已處理,未提交;事務B也在此時新增了一條未處理的記錄,並提交了;事務A隨後查詢記錄,卻發現有一條記錄是未處理的造成幻讀現象,幻讀僅專指新插入的行。幻讀會造成語義上的問題跟數據一致性問題。

4、 在可重復讀RR隔離級別下,普通查詢是快照讀,是不會看到別的事務插入的數據的。因此,幻讀在當前讀下才會出現。要用間隙鎖解決此問題。

在說隔離級別之前,你首先要知道,你隔離得越嚴實,效率就會越低。因此很多時候,我們都要在二者之間尋找一個平衡點。SQL標準的事務隔離級別由低到高如下: 上圖從上到下的模式會導致系統的並行性能依次降低,安全性依次提高。

讀未提交:別人改數據的事務尚未提交,我在我的事務中也能讀到。

讀已提交(Oracle默認):別人改數據的事務已經提交,我在我的事務中才能讀到。

可重復讀(MySQL默認):別人改數據的事務已經提交,我在我的事務中也不去讀,以此保證重復讀一致性。

串列:我的事務尚未提交,別人就別想改數據。

標准跟實現:上面都是關於事務的標准,但是每一種資料庫都有不同的實現,比如MySQL InnDB 默認為RR級別,但是不會出現幻讀。因為當事務A更新了所有記錄的某個欄位,此時事務A會獲得對這個表的表鎖,因為事務A還沒有提交,所以事務A獲得的鎖沒有釋放,此時事務B在該表插入新記錄,會因為無法獲得該表的鎖,則導致插入操作被阻塞。只有事務A提交了事務後,釋放了鎖,事務B才能進行接下去的操作。所以可以說 MySQL的RR級別的隔離是已經實現解決了臟讀,不可重復讀和幻讀的。

5、MySQL中的鎖

無論是Java的並發編程還是資料庫的並發操作都會涉及到鎖,研發人員引入了悲觀鎖跟樂觀鎖這樣一種鎖的設計思想。

悲觀鎖:

優點:適合在寫多讀少的並發環境中使用,雖然無法維持非常高的性能,但是在樂觀鎖無法提更好的性能前提下,可以做到數據的安全性

缺點:加鎖會增加系統開銷,雖然能保證數據的安全,但數據處理吞吐量低,不適合在讀書寫少的場合下使用

樂觀鎖:

優點:在讀多寫少的並發場景下,可以避免資料庫加鎖的開銷,提高DAO層的響應性能,很多情況下ORM工具都有帶有樂觀鎖的實現,所以這些方法不一定需要我們人為的去實現。

缺點:在寫多讀少的並發場景下,即在寫操作競爭激烈的情況下,會導致CAS多次重試,沖突頻率過高,導致開銷比悲觀鎖更高。

實現:資料庫層面的樂觀鎖其實跟CAS思想類似, 通數據版本號或者時間戳也可以實現。

資料庫並發場景主要有三種:

讀-讀:不存在任何問題,也不需要並發控制

讀-寫:有隔離性問題,可能遇到臟讀,幻讀,不可重復讀

寫-寫:可能存更新丟失問題,比如第一類更新丟失,第二類更新丟失

兩類更新丟失問題:

第一類更新丟失:事務A的事務回滾覆蓋了事務B已提交的結果 第二類更新丟失:事務A的提交覆蓋了事務B已提交的結果

為了合理貫徹落實鎖的思想,MySQL中引入了雜七雜八的各種鎖:

鎖分類

MySQL支持三種層級的鎖定,分別為

表級鎖定

MySQL中鎖定粒度最大的一種鎖,最常使用的MYISAM與INNODB都支持表級鎖定。

頁級鎖定

是MySQL中鎖定粒度介於行級鎖和表級鎖中間的一種鎖,表級鎖速度快,但沖突多,行級沖突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。

行級鎖定

Mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少資料庫操作的沖突。其加鎖粒度最小,但加鎖的開銷也最大行級鎖不一定比表級鎖要好:鎖的粒度越細,代價越高,相比表級鎖在表的頭部直接加鎖,行級鎖還要掃描找到對應的行對其上鎖,這樣的代價其實是比較高的,所以表鎖和行鎖各有所長。

MyISAM中的鎖

雖然MySQL支持表,頁,行三級鎖定,但MyISAM存儲引擎只支持表鎖。所以MyISAM的加鎖相對比較開銷低,但數據操作的並發性能相對就不高。但如果寫操作都是尾插入,那還是可以支持一定程度的讀寫並發

從MyISAM所支持的鎖中也可以看出,MyISAM是一個支持讀讀並發,但不支持通用讀寫並發,寫寫並發的資料庫引擎,所以它更適合用於讀多寫少的應用場合,一般工程中也用的較少。

InnoDB中的鎖

該模式下支持的鎖實在是太多了,具體如下:

共享鎖和排他鎖 (Shared and Exclusive Locks)

意向鎖(Intention Locks)

記錄鎖(Record Locks)

間隙鎖(Gap Locks)

臨鍵鎖 (Next-Key Locks)

插入意向鎖(Insert Intention Locks)

主鍵自增鎖 (AUTO-INC Locks)

空間索引斷言鎖(Predicate Locks for Spatial Indexes)

舉個栗子,比如行鎖里的共享鎖跟排它鎖:lock in share modle 共享讀鎖:

為了確保自己查到的數據沒有被其他的事務正在修改,也就是說確保查到的數據是最新的數據,並且不允許其他人來修改數據。但是自己不一定能夠修改數據,因為有可能其他的事務也對這些數據使用了 in share mode 的方式上了S 鎖。如果不及時的commit 或者rollback 也可能會造成大量的事務等待。

for update排它寫鎖:

為了讓自己查到的數據確保是最新數據,並且查到後的數據只允許自己來修改的時候,需要用到for update。相當於一個 update 語句。在業務繁忙的情況下,如果事務沒有及時的commit或者rollback 可能會造成其他事務長時間的等待,從而影響資料庫的並發使用效率。

Gap Lock間隙鎖:

1、行鎖只能鎖住行,如果在記錄之間的間隙插入數據就無法解決了,因此MySQL引入了間隙鎖(Gap Lock)。間隙鎖是左右開區間。間隙鎖之間不會沖突。

2、間隙鎖和行鎖合稱NextKeyLock,每個NextKeyLock是前開後閉區間。

間隙鎖加鎖原則(學完忘那種):

1、加鎖的基本單位是 NextKeyLock,是前開後閉區間。

2、查找過程中訪問到的對象才會加鎖。

3、索引上的等值查詢,給唯一索引加鎖的時候,NextKeyLock退化為行鎖。

4、索引上的等值查詢,向右遍歷時且最後一個值不滿足等值條件的時候,NextKeyLock退化為間隙鎖。

5、唯一索引上的范圍查詢會訪問到不滿足條件的第一個值為止。

⑶ sql server有聯合主鍵是否也有聯合索引,怎樣創建聯合索引

create index 索引名 on 表名(欄位名1,欄位名2,...欄位名n)

⑷ 聯合索引

本文預計分為兩個部分:

(1)聯合索引部分的基礎知識

在這個部分,我們溫習一下聯合索引的基礎

(2)聯合索引部分的實戰題

在這個部分,列舉幾個我認為算是實戰中的代表題,挑出來帶沖說說。

正文

基礎

講聯合索引,一定要扯最左匹配!放心,我不扯有的沒的,幾句話懂個大概就行!

最左匹配

所謂最左原則指的就是如果你的 SQL 語句中用到了聯合索引中的最左邊的索引,掘行晌那麼這條 SQL 語句就可以利用這個聯合索引去進行匹配,值得注意的是,當遇到范圍查詢(>、<、between、like)就會停止匹配。

假設,我們對(a,b)欄位建立一個索引,也就是說,你where後條件為

a=1a=1and b =2

是可以匹配索引的。但是要注意的是~你執行

b=2and a =1

也是能匹配到索引的,因為Mysql有優化器會自動調整a,b的順序與索引順序一致。

相反的,你執行

b=2

就匹配不到索引了。

而你對(a,b,c,d)建立索引,where後條件為

a =1andb =2andc >3andd =4

那麼,a,b,c三個欄位能用到索引,而d就匹配不到。因為遇到了范圍查詢!

最左匹配的原理?

假設,我們對判鋒(a,b)欄位建立索引,那麼入下圖所示

如圖所示他們是按照a來進行排序,在a相等的情況下,才按b來排序。

因此,我們可以看到a是有序的1,1,2,2,3,3。而b是一種全局無序,局部相對有序狀態!

什麼意思呢?

從全局來看,b的值為1,2,1,4,1,2,是無序的,因此直接執行b = 2這種查詢條件沒有辦法利用索引。

從局部來看,當a的值確定的時候,b是有序的。例如a = 1時,b值為1,2是有序的狀態。當a=2時候,b的值為1,4也是有序狀態。

因此,你執行a = 1 and b = 2是a,b欄位能用到索引的。而你執行a > 1 and b = 2時,a欄位能用到索引,b欄位用不到索引。因為a的值此時是一個范圍,不是固定的,在這個范圍內b值不是有序的,因此b欄位用不上索引。

綜上所示,最左匹配原則,在遇到范圍查詢的時候,就會停止匹配。

實戰

OK,懂上面的基礎,我們就可以開始扯了~我舉了經典的五大題型,看完基本就懂!

題型一

如果sql為

SELECT*FROMtableWHEREa =1andb =2andc =3;

如何建立索引?

如果此題回答為對(a,b,c)建立索引,那都可以回去等通知了。

此題正確答法是,(a,b,c)或者(c,b,a)或者(b,a,c)都可以,重點要的是將區分度高的欄位放在前面,區分度低的欄位放後面。像性別、狀態這種欄位區分度就很低,我們一般放後面。

例如假設區分度由大到小為b,a,c。那麼我們就對(b,a,c)建立索引。在執行sql的時候,優化器會 幫我們調整where後a,b,c的順序,讓我們用上索引。

題型二

如果sql為

SELECT*FROMtableWHEREa >1andb =2;

如何建立索引?

如果此題回答為對(a,b)建立索引,那都可以回去等通知了。

此題正確答法是,對(b,a)建立索引。如果你建立的是(a,b)索引,那麼只有a欄位能用得上索引,畢竟最左匹配原則遇到范圍查詢就停止匹配。

如果對(b,a)建立索引那麼兩個欄位都能用上,優化器會幫我們調整where後a,b的順序,讓我們用上索引。

題型三

如果sql為

SELECT*FROM`table`WHEREa >1andb =2andc >3;

如何建立索引?

此題回答也是不一定,(b,a)或者(b,c)都可以,要結合具體情況具體分析。

拓展一下

SELECT*FROM`table`WHEREa =1andb =2andc >3;

怎麼建索引?嗯,大家一定都懂了!

題型四

SELECT*FROM`table`WHEREa =1ORDERBYb;

如何建立索引?

這還需要想?一看就是對(a,b)建索引,當a = 1的時候,b相對有序,可以避免再次排序!

那麼

SELECT*FROM`table`WHEREa >1ORDERBYb;

如何建立索引?

對(a)建立索引,因為a的值是一個范圍,這個范圍內b值是無序的,沒有必要對(a,b)建立索引。

拓展一下

SELECT*FROM`table`WHEREa =1ANDb =2ANDc >3ORDERBYc;

怎麼建索引?

題型五

SELECT*FROM`table`WHEREaIN(1,2,3)andb >1;

如何建立索引?

還是對(a,b)建立索引,因為IN在這里可以視為等值引用,不會中止索引匹配,所以還是(a,b)!

拓展一下

SELECT*FROM`table`WHEREa =1ANDbIN(1,2,3)ANDc >3ORDERBYc;

如何建立索引?此時c排序是用不到索引的。

⑸ SQL不走索引的可能原因

1、聯合索引,查詢條件沒有聯合櫻正索引的第一列。

2、在包含有null值的table列上建立索引,當時使用select count(*) from table時不會使用索引。

3、在索引列上使用函數時不會使用索引,如果一定要使用索引只能建立函數索引。

4、當被索引的列進行隱式碼大的類型轉換時不會使用索引。

5、使用 IS NULL 和 IS NOT NULL

6、使用 LIKE 『%T』 進行模糊查詢,要脊模悔走索引,like的後面不能以%開頭

7、WHERE 子句中使用不等於操作

8、等於和范圍索引不會被合並使用

⑹ mysql資料庫創建兩張表之間的聯合索引的sql語句,示例就可以!多謝

ALTERTABLEOrdersADDFOREIGNKEY(Id_P)
REFERENCESPersons(Id_P)

⑺ mysql建表時如何把兩個欄位加一起指定為唯一索引

mysql無法在建表時把兩個欄位加一起指定歲埋做為唯一索引。mysql設置聯合唯一索引方法如下:使用Altertable表名addUNIQUEindex索引名(欄位1,欄位2)語液巧句來設置,它會刪除重復的乎衡記錄,保留一條,然後建立聯合唯一索引。

⑻ 聯合索引(x+y),那麼sql語句的where條件上大於小於范圍的哪種寫法效率高

1、首先復合索引中列的次序很重要,如果index on (x,y),一般來說x的選擇性要比y的選擇性高比較好,如果x的選擇性足和蠢夠高,只對單列x提條件時也可能會用上這個索引
2、你這2個條件對於目前的大型資料庫沒差別,資料庫在做執行畝棚基計劃都會進行優化,當然代碼還是盡量做到不依賴於資料庫的優化
3、如果想優化這個條件,個人覺得應該寫成迅謹 x between 11 and 49 and y between 11 and 49,如果復合索引中x在y前

⑼ Mysql建立索引經驗

在實際開發中使用資料庫時,難免會遇到一些大表數據,對這些數據進行查詢時,有時候SQL會查詢得特別慢,這時候,有經驗的老師傅會告訴你,你看一下哪幾個欄位查的多,加一個索引就好了。

那麼,怎麼合理地建立索引呢?這里分享一下我的一些經驗,如有不妥之處,歡迎批評指正。

1、不要盲目建立索引 , 先分析再創建

索引雖然能大幅度提升我們的查詢性能,但也要知道,在你進行增刪改時,索引樹也要同樣地進行維護。所以,索引不是越多越好,而是按需建立。最好是在一整塊模塊開發完成後,分析一下,去針對大多數的查詢,建立聯合索引。

2、使用聯合索引盡量覆蓋多的條件

這是說在一個慢sql里假如有五個where ,一個 order by ,那麼我們的聯合索引盡量覆蓋到這五個查詢條件,如果有必要,order by 也覆蓋上 。

3、小基數欄位不需要索引

這個意思是,如果一張表裡某個欄位的值只有那麼幾個,那麼你針對這個欄位建立的索引其實沒什麼意義,比如說,一個性別欄位就兩種結果,你建了索引,排序也沒什麼意思(也就是索引里把男女給分開了)

所以說,索引盡量選擇基數大的數據去建立宴肆,能最大化地利用索引

4、長字元串可以使用前綴索引

我們建立索引的欄位盡量選擇欄位類型知喚較小的,比如一個varchar(20)和varchar(256)的,我們在20的上晌猛轎面建立的索引和在256上就有明顯的差距(字元串那麼長排序也不好排呀,唉)。

當然,如果一定是要對varchar(256)建立索引,我們可以選擇裡面的前20個字元放在索引樹里(這里的20不絕對,選擇能盡量分辨數據的最小字元欄位設計),類似這樣KEY index(name(20),age,job) ,索引只會對name的前20個字元進行搜索,但前綴索引無法適用於order by 和 group by。

5、對排序欄位設計索引的優先順序低

如果一個SQL里我們出現了范圍查找,後邊又跟著一個排序欄位,那麼我們優先給范圍查找的欄位設置索引,而不是優先排序。

6、如果出現慢SQL,可以設計一個只針對該條SQL的聯合索引。

不過慢SQL的優化,需要一步步去進行分析,可以先用explain查看SQL語句的分析結果,再針對結果去做相應的改進。explain的東西我們下次再講。

PS:在 select 語句之前增加 explain 關鍵字,MySQL 會在查詢上設置一個標記,執行查詢會返回執行計劃的信息,而不是 執行這條SQL。

⑽ SQL Server 怎麼建立聯合主鍵

建立聯合主鍵有兩種方式:

一種是在建表時就寫出,語句如下:

Create Table 表名 (欄位名1 Int Not Null,

欄位名2 nvarchar(13) Not Null Primary Key (欄位名1, 欄位名2),

欄位名3…………

欄位名N………… )

另一種是在建表後更改,語句如下:

alter table 你的表名 add constraint pk_你的表名 primary key (欄位1,欄位2)

ALTER TABLE 表名 WITH NOCHECK ADD

CONSTRAINT [PK_表名] PRIMARY KEY NONCLUSTERED

(

[欄位名1],

[欄位名2]

)

創建聯合主鍵還可以這樣寫:

create table huayunkeji_today(device_id int , year int, month int, day int, hour int, temperature float, humidity float,

primary key(device_id,year,month,day,hour));

(10)建立聯合索引的sql擴展閱讀:

聯合主鍵的使用情況及優點:

聯合主鍵就是用2個或2個以上的欄位組成主鍵。用這個主鍵包含的欄位作為主鍵,這個組合在數據表中是唯一,且加了主鍵索引。

可以這么理解,比如,你的訂單表裡有很多欄位,一般情況只要有個訂單號bill_no做主鍵就可以了,但是,現在要求可能會有補充訂單,使用相同的訂單號,那麼這時單獨使用訂單號就不可以了。

再使用個訂單序列號bill_seq來作為區別。把bill_no和bill_seq設成聯合主鍵。即使bill_no相同,bill_seq不同也是可以的。