web-dev-qa-db-ja.com

Postgresqlは非ASCIILIKEクエリを実行するときにGINトリグラムインデックスを使用しませんか?

再現する手順

データベースを作成する

_CREATE DATABASE citiesdb
  WITH OWNER = citiesowner
       ENCODING = 'UTF8'
       TABLESPACE = pg_default
       LC_COLLATE = 'C'
       LC_CTYPE = 'C'
       CONNECTION LIMIT = -1;
_

データベースを作成した後、Erwinの回答からsql fiddleからコードを実行できます https://dba.stackexchange.com/a/63202/37108http://sqlfiddle.com /#!12/270e2/1 )または、質問の最後にある追加情報をお読みください。

ASCII文字のみでLIKEクエリを実行する

_EXPLAIN ANALYZE SELECT * FROM city WHERE other_names_lower like '%ele%';

"Bitmap Heap Scan on city  (cost=16.10..64.02 rows=13 width=147) (actual time=0.642..3.303 rows=513 loops=1)"
"  Recheck Cond: (other_names_lower ~~ '%ele%'::text)"
"  ->  Bitmap Index Scan on other_names_lower_trgm_gin  (cost=0.00..16.10 rows=13 width=0) (actual time=0.486..0.486 rows=513 loops=1)"
"        Index Cond: (other_names_lower ~~ '%ele%'::text)"
"Total runtime: 3.439 ms"
_

非ASCII文字を使用してLIKEクエリを実行する

_explain analyze SELECT * FROM city WHERE (other_names_lower like '%желез%')

"Seq Scan on city  (cost=0.00..1693.53 rows=5 width=134) (actual time=33.498..58.688 rows=9 loops=1)"
"  Filter: (other_names_lower ~~ '%желез%'::text)"
"  Rows Removed by Filter: 46673"
"Total runtime: 58.753 ms"
_

質問

非ASCIIテキストを検索する場合、エンジンはGINトリグラムインデックスの代わりにシーケンシャルスキャンを使用しています。なぜそれを行うのですか?ルックアップを高速化するためにインデックス、クエリ、またはデータベースを構築するための代替方法は何ですか?

追加情報

PostgreSQL 9.2; Windows 864ビット。

テーブル定義の一部(_[...]_は他の列です)。

CREATE TABLE city ([...] other_names_lower text [...]) WITH ( OIDS=FALSE );

列other_names_lowerには、都市のさまざまな名前が含まれています。行には、中国語、ポーランド語、ロシア語、およびその他の文字範囲が含まれます。

インデックス作成コード

_CREATE EXTENSION pg_trgm;

CREATE INDEX other_names_lower_trgm_gin
  ON city
  USING gin
  (other_names_lower gin_trgm_ops);
_

その他の設定-コメントでDanielVéritéによって提案されたクエリ

_select name, source, setting from pg_settings where source <> 'default' and source <> 'override';

"application_name";"client";"pgAdmin III - Narz??dzie Zapytania"
"bytea_output";"session";"escape"
"client_encoding";"session";"UNICODE"
"client_min_messages";"session";"notice"
"DateStyle";"session";"ISO, YMD"
"default_text_search_config";"configuration file";"pg_catalog.simple"
"enable_seqscan";"session";"on"
"lc_messages";"configuration file";"en_US.UTF-8"
"lc_monetary";"configuration file";"Polish_Poland.1250"
"lc_numeric";"configuration file";"Polish_Poland.1250"
"lc_time";"configuration file";"Polish_Poland.1250"
"listen_addresses";"configuration file";"*"
"log_destination";"configuration file";"stderr"
"log_line_prefix";"configuration file";"%t "
"log_statement";"configuration file";"all"
"log_timezone";"configuration file";"Europe/Sarajevo"
"logging_collector";"configuration file";"on"
"max_connections";"configuration file";"100"
"max_stack_depth";"environment variable";"2048"
"port";"configuration file";"5432"
"shared_buffers";"configuration file";"4096"
"TimeZone";"configuration file";"Europe/Sarajevo"
_
2
user44

COLLATE = "C"を使用してシナリオを作成しましたが、どちらのクエリもother_names_lower_trgm_ginのビットマップインデックススキャンインデックスを期待どおりに使用しています。

SQL Fiddle 〜10k行のテーブル、Postgres 9.2.4、COLLATE = "C"

あなたの質問にnotであるあなたのセットアップにおそらく何か問題があります。
実行(大きなテーブルと排他ロックには時間がかかります!):

VACUUM FULL ANALYZE city;

そしてさらに試みる ...

1