Вы не могли бы пояснить, о чём именно речь?
Попробую на пальцах.
Данные в индексе хранятся блоками по 8 килобайт. Если базе нужна лишь одна строка, то всё равно загружается весь блок.
В наших интересах сделать так, чтобы в загружаемом блоке нужными оказались _все_ строки, а не какая-то одна.
Допустим, в таблице (a,b) находятся такие записи: (1,1) (1,2) (1,3) (1,4) (2,1) (2,2) (2,3) (2,4)
Допустим, в индексный блок помещается лишь 2 записи (в реальности, конечно, в 8кб помещается штук 50-100, но суть это не меняет)
Допустим, запрашиваться будут данные по a=1 and b in (1,2,3,4)
Индекс (a,b) будет выглядеть следующим образом:
блок1: (1,1) (1,2)
блок2: (1,3) (1,4)
блок3: (2,1) (2,2)
блок4: (2,3) (2,4)
Запрос (один через in или 4 раздельных) в конечном итоге загрузят блок1 и блок2. Т.е. мы загрузили 2 блока данных с диска, и в них оказались нужные нам строки.
Индекс (b,a) будет выглядеть по-другому (самый простой способ понять, это представить как будет выглядеть результат order by b,a )
блок1: (1,1) (2,1)
блок2: (1,2) (2,2)
блок3: (1,3) (2,3)
блок4: (1,4) (2,4)
Для загрузки нужных нам четырёх строк придётся загрузить все 4 блока. В каждом будет одна нужная строка, и одна ненужная.
Получается, что при таких входных данных индекс (b,a) будет требовать больше места в buffer cache, он будет хуже работать после перезагрузок (ну или подобных действий, когда сбрасывается кэш).
Хотя, «в среднем по больнице», колонка b более селективная и «вроде как она должна быть 1-ой в индексе»