這個問題並不弱智,需要對查詢最佳化器比較瞭解才能理解為什麼沒有用索引,而查詢最佳化器是資料庫裡非常複雜的部分。它的目標是接受使用者的SQL語句,生成一個最好的查詢計劃。不過這個問題還是比較容易解釋的,查詢最佳化器在選擇查詢計劃的時候,會對不同查詢計劃進行評估(透過一個cost function),選擇它認為執行最快的查詢計劃。你這個查詢可以有兩種查詢計劃,一個是表掃描(table scan),一個是利用索引(B+tree)至於這兩個計劃哪個快,需要看具體的資料是怎樣的,並不是索引總會比表掃描快,舉個例子:如果你那個表T1有100萬行記錄,其中50萬行的I2都是1,selectivity為50%,這時明顯用表掃描快,因為用表掃描,掃描全部100萬行記錄就可以了。而如果用B+tree,如果底層儲存是索引組織表,由於你的I2是非聚簇索引,需要現在I2的B+tree中找I2為1的記錄的主鍵Id,然後再去Id的B+tree中找這個tuple,才能完成一次查詢,然後由於非聚簇B+樹索引中I2為1的元素所在葉子節點透過指標連線起來了,後面的不需要再在I2的B+tree的根節點出發,直接透過連結串列可以獲得,但仍然需要50萬次的Id的B+tree的查詢,顯然效率很差。雖然如果底層儲存為堆表,只需要在I2的B+tree中找就可以了,但仍需要透過指標到底層儲存,去獲取整個tuple,效率扔不如表掃描。但如果你那個表中只有1行的I2為1,selectivity幾乎為0,那麼只需要一次索引掃描就可以了,而用表掃描仍需要掃表整個表的所有資料,因此此時用索引更好。根據經驗來看,selectivity為10%是臨界點(使用普通硬碟時),低於10%用索引更優,高於10%用表掃描更優,不過實際上要根據硬體進行調整,比如你用的是普通硬碟還是SSD。你可以看一下你查詢結果的數量,然後和總行數比較一下,比值應該是比較大的。select count(*) from T1 where I2=1;select count(*) from T1;
這個問題並不弱智,需要對查詢最佳化器比較瞭解才能理解為什麼沒有用索引,而查詢最佳化器是資料庫裡非常複雜的部分。它的目標是接受使用者的SQL語句,生成一個最好的查詢計劃。不過這個問題還是比較容易解釋的,查詢最佳化器在選擇查詢計劃的時候,會對不同查詢計劃進行評估(透過一個cost function),選擇它認為執行最快的查詢計劃。你這個查詢可以有兩種查詢計劃,一個是表掃描(table scan),一個是利用索引(B+tree)至於這兩個計劃哪個快,需要看具體的資料是怎樣的,並不是索引總會比表掃描快,舉個例子:如果你那個表T1有100萬行記錄,其中50萬行的I2都是1,selectivity為50%,這時明顯用表掃描快,因為用表掃描,掃描全部100萬行記錄就可以了。而如果用B+tree,如果底層儲存是索引組織表,由於你的I2是非聚簇索引,需要現在I2的B+tree中找I2為1的記錄的主鍵Id,然後再去Id的B+tree中找這個tuple,才能完成一次查詢,然後由於非聚簇B+樹索引中I2為1的元素所在葉子節點透過指標連線起來了,後面的不需要再在I2的B+tree的根節點出發,直接透過連結串列可以獲得,但仍然需要50萬次的Id的B+tree的查詢,顯然效率很差。雖然如果底層儲存為堆表,只需要在I2的B+tree中找就可以了,但仍需要透過指標到底層儲存,去獲取整個tuple,效率扔不如表掃描。但如果你那個表中只有1行的I2為1,selectivity幾乎為0,那麼只需要一次索引掃描就可以了,而用表掃描仍需要掃表整個表的所有資料,因此此時用索引更好。根據經驗來看,selectivity為10%是臨界點(使用普通硬碟時),低於10%用索引更優,高於10%用表掃描更優,不過實際上要根據硬體進行調整,比如你用的是普通硬碟還是SSD。你可以看一下你查詢結果的數量,然後和總行數比較一下,比值應該是比較大的。select count(*) from T1 where I2=1;select count(*) from T1;