Operator "~<~" uses varchar_pattern_ops index while normal ORDER BY clause doesn't?
This revolves around COLLATION rules (which are part of your locale). Per documentation:


  The C and POSIX collations both specify "traditional C" behavior,
  in which only the ASCII letters "A" through "Z" are treated as
  letters, and sorting is done strictly by character code byte values.


Bold emphasis mine. These internal operators:

~&lt;~, ~&lt;=~, ~&gt;=~, ~&gt;~

are members of the operator classes text_pattern_ops, varchar_pattern_ops and bpchar_pattern_ops which ignore current collation rules and default to "traditional C" behavior. Per documentation:


  The difference from the default operator classes is that the values
  are compared strictly character by character rather than according to
  the locale-specific collation rules.


That's why they can use your first index, while their locale-aware equivalents

&lt;, &lt;=, &gt;=, &gt;

would need the second (using the default operator class).

ORDER BY defaults to the current collation rules. Unless you happen to work with the "C" collation the second set of operators is used for sorting, which can only use indexes with a matching collation (default btree indexes).

Notably, pattern-matching generally relies on "traditional C" behavior, that's why a left anchored LIKE match can use a _patern_ops index with a non-C locale, but not a default index. Compare (last chapter):


Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL


In Postgres 9.1+ you can force a selected sort order with COLLATE "locale_name" (the locale has to be available in your system!). So if you run your query with COLLATE "C" (which is a much better option than the evil hack using ~&lt;~) , it can use the _pattern_ops index:

SELECT * FROM individual
ORDER  BY upper(surname) COLLATE "C"
        , upper("name") COLLATE "C"
        , upper(patronymic) COLLATE "C"
        , birth_dt
LIMIT  100;

Results are different. Try with non-ASCII letters like ö,  é, etc. Those typically sort depending on your current collation rules, while letters a-z typically sort the same in all locales.