Other answers clarified that trigram indexes are based on alphanumeric characters only. That's why all your examples match 100 %.

You may still be able to make use of a trigram GiST or GIN index *and* establish your desired sort order with additional `ORDER BY` expressions. For your demonstrated case:

    SELECT my_column, similarity('$ Hello', my_column) AS sml
    FROM   my_table
    WHERE  my_column % '$ Hello'
    ORDER  BY sml DESC
            , my_column <> '$ Hello'       -- !
            , my_column;

The boolean expression `my_column <> '$ Hello'` evaluates to `FALSE`, `TRUE`, or `NULL` - with *this* sort order. So the exact match (considering *all* characters) comes first. And this query can still use a trigram index. A trigram GiST index would (still) even support a **"nearest neighbor"** (KNN) search with `LIMIT`. Related:

- [Search in 300 million addresses with pg_trgm][1]
- [Optimizing a postgres similarity query (pg_trgm + gin index)][2]

You can do more, depends on your exact use case and requirements. Example:

    ...
    ORDER  BY sml DESC
            , my_column <> '$ Hello'
            , my_column !~ '\$ Hello'            -- note $ escaped with \$
            , levenshtein(my_column , '$ Hello')
            , my_column;

Within the same trigram similarity, this sorts exact matches first, then strings *containing* the exact phrase. And within each subgroup matches the shorter Levenshtein distance first. Alphabetical as final tiebreaker. Related:

- https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql/10696#10696
- https://dba.stackexchange.com/questions/33137/postgresql-8-4-no-levenshtein-fuzzymatching/33138#33138
- [Escape function for regular expression or LIKE patterns][3]

Last but not least, you tagged **[full text search][4]**. But your example is based on trigram similarity (provided by the additional module [`pg_trgm`][5]), which is a largely different concept with completely separate infrastructure and operators. You may want actual full text search instead (and phrase search with that?):

- https://dba.stackexchange.com/questions/204588/how-to-search-hyphenated-words-in-postgresql-full-text-search/204601#204601

But punctuation characters are considered noise and stripped in FTS all the same. Same "problem". `ts_debug()` shows how your text search configuration classifies identified tokens in a given string (`simple` configuration in the example). 

    SELECT * FROM ts_debug('simple', '? Hello %&/( 123');

It starts with the "default" parser (which is currently the only one), parsing all these as noise to begin with ...


  [1]: https://stackoverflow.com/a/44838192/939860
  [2]: https://stackoverflow.com/q/43867449/939860
  [3]: https://stackoverflow.com/a/45741630/939860
  [4]: https://www.postgresql.org/docs/current/textsearch.html
  [5]: https://www.postgresql.org/docs/current/pgtrgm.html