典型的なEAVスキーマに関するクエリがあります。
SELECT contacts.id
FROM contacts
LEFT OUTER JOIN (SELECT DISTINCT contacts_values.company_id AS company_id, contacts_values.id AS id
FROM contacts_values
WHERE contacts_values.field_id = '\x000000000000000000000000'
AND contacts_values.field_name = 'facebook'
AND nimble_contact_value_normalize(nimble_skip_long_values(contacts_values.value)) =
nimble_contact_value_normalize('http://www.facebook.com/jon.ferrara')) AS anon_1
ON anon_1.company_id = contacts.company_id AND anon_1.id = contacts.id
LEFT OUTER JOIN (SELECT DISTINCT contacts_values.company_id AS company_id, contacts_values.id AS id
FROM contacts_values
WHERE contacts_values.field_id = '\x000000000000000000000000'
AND contacts_values.field_name = 'last_name'
AND nimble_contact_value_normalize(nimble_skip_long_values(contacts_values.value)) =
nimble_contact_value_normalize('Ferrara')) AS anon_2
ON anon_2.company_id = contacts.company_id AND anon_2.id = contacts.id
JOIN contacts__aggregated AS contacts__aggregated_1
ON contacts__aggregated_1.company_id = contacts.company_id AND
contacts__aggregated_1.contact_id = contacts.id AND contacts__aggregated_1.field_name = 'names'
WHERE contacts.company_id = '\x4c2118ad54397f271b000000'
AND (anon_1.id IS NOT NULL OR anon_2.id IS NOT NULL)
ORDER BY contacts__aggregated_1.value ASC
LIMIT 30 OFFSET 0;
私の問題は、このクエリのLIMIT句により、プランナーがネストされたループを持つ不適切なプランを選択するようになることです: https://explain.depesz.com/s/Mute 。 SET ENABLE_NESTLOOP TO OFF
の後に同じクエリを実行すると、はるかに効率的な計画が得られます: https://explain.depesz.com/s/b5kn 。クエリからLIMITを削除すると、同様の計画になります: https://explain.depesz.com/s/wDqE 。
私が懸念していることの1つは、ネストされていないループプランのLIMITノードのコストがそのサブノードのコストのほんの一部であるということです。ただし、マージ結合プランを改善するために、LIMITノードのコストはサブノードと同じです。どうしてこのようになるのでしょうか?そして、プランナーがより良いプランを選択できるようにするにはどうすればよいですか?
PostgreSQL10.10を実行しています。
を使用してインデックスを使用しないようにPostgreSQLに指示します
_ORDER BY contacts__aggregated_1.value + 0 ASC
_
問題は、PostgreSQLがインデックスを使用して_contacts__aggregated
_の順序で_ORDER BY
_をスキャンし、ネストされたループを使用して他のテーブルから行を追加し、満たさない値を除外すると、最速になると考えていることです。状況、契約条項。
多くの値が除外されない場合、これは多くの場合、優れた戦略です。
しかし、それは悪い計画を生み出します
value
を持っていますこれらのことの1つが起こったに違いありません。 EXPLAIN (ANALYZE, BUFFERS)
出力で高い_Rows removed by filter
_を探します。