このデータベースに対するフルテキストクエリ(RT(リクエストトラッカー)チケットを格納する)は、実行に非常に長い時間がかかるようです。添付ファイルテーブル(フルテキストデータを含む)は約15GBです。
データベーススキーマは次のとおりで、約200万行です。
rt4 =#\ d +添付ファイル
テーブル "public.attachments"
コラム| タイプ| 修飾子| ストレージ| 説明文
----------------- + ----------------------------- +- -------------------------------------------------- ------ + ---------- + -------------
id | 整数| nullではないデフォルトのnextval( 'attachments_id_seq' :: regclass)| プレーン|
transactionid | 整数| nullではない| プレーン|
親| 整数| nullではないデフォルト0 | プレーン|
メッセージID | キャラクター変化(160)| | 拡張|
件名| 文字の変化(255)| | 拡張|
ファイル名| 文字の変化(255)| | 拡張|
contenttype | 文字の変化(80)| | 拡張|
contentencoding | 文字の変化(80)| | 拡張|
コンテンツ| テキスト| | 拡張|
ヘッダー| テキスト| | 拡張|
クリエーター| 整数| nullではないデフォルト0 | プレーン|
作成しました| タイムゾーンなしのタイムスタンプ| | プレーン|
contentindex | tsvector | | 拡張|
インデックス:
"attachments_pkey" PRIMARY KEY、btree(id)
"attachments1" btree(親)
"attachments2" btree(トランザクションID)
"attachments3" btree(親、transactionid)
「contentindex_idx」ジン(contentindex)
OIDあり:いいえ
次のようなクエリを使用して、データベース自体を非常にすばやく(1秒未満で)クエリできます。
select objectid
from attachments
join transactions on attachments.transactionid = transactions.id
where contentindex @@ to_tsquery('frobnicate');
ただし、RTが同じテーブルで全文索引検索を実行することになっているクエリを実行すると、通常、完了するまでに数百秒かかります。クエリ分析の出力は次のとおりです。
クエリ
SELECT COUNT(DISTINCT main.id)
FROM Tickets main
JOIN Transactions Transactions_1 ON ( Transactions_1.ObjectType = 'RT::Ticket' )
AND ( Transactions_1.ObjectId = main.id )
JOIN Attachments Attachments_2 ON ( Attachments_2.TransactionId = Transactions_1.id )
WHERE (main.Status != 'deleted')
AND ( ( ( Attachments_2.ContentIndex @@ plainto_tsquery('frobnicate') ) ) )
AND (main.Type = 'ticket')
AND (main.EffectiveId = main.id);
EXPLAIN ANALYZE 出力
クエリプラン
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------
集計(コスト= 51210.60..51210.61行= 1幅= 4)(実際の時間= 477778.806..477778.806行= 1ループ= 1)
->ネストされたループ(コスト= 0.00..51210.57行= 15幅= 4)(実際の時間= 17943.986..477775.174行= 4197ループ= 1)
->ネストされたループ(コスト= 0.00..40643.08行= 6507幅= 8)(実際の時間= 8.526..20610.380行= 1714818ループ= 1)
->チケットのメインのシーケンススキャン(コスト= 0.00..9818.37行= 598幅= 8)(実際の時間= 0.008..256.042行= 96990ループ= 1)
フィルター:((((status):: text 'deleted' :: text)AND(id = effectiveid)AND((type):: text = 'ticket' :: text))
->トランザクションtransactions_1(cost = 0.00..51.36 rows = 15 width = 8)のトランザクション1を使用したインデックススキャン(実際の時間= 0.102..0.202行= 18ループ= 96990)
インデックス条件:(((objecttype):: text = 'RT :: Ticket' :: text)AND(objectid = main.id))
->添付ファイルattachments_2のattachments2を使用したインデックススキャン(コスト= 0.00..1.61行= 1幅= 4)(実際の時間= 0.266..0.266行= 0ループ= 1714818)
インデックス条件:(transactionid = transaction_1.id)
フィルター:(contentindex @@ plainto_tsquery( 'frobnicate' :: text))
合計実行時間:477778.883 ms
私の知る限り、問題はcontentindexフィールド(contentindex_idx)で作成されたインデックスを使用しておらず、添付ファイルテーブル内の一致する多数の行に対してフィルターを実行していることです。ANALYZEEXPLAIN 出力の行数も、最近の推定行数= 6507の実際の行数= 1714818になった後でも、非常に不正確であるように見えます。
これで次にどこへ行くのか本当に分かりません。