دوال Postgres والاستعلامات غير القابلة للفهرسة (Non-sargable)
قد يؤدي استخدام دوال postgres داخل عبارة where إلى جعل الاستعلام non-sargable، أي غير قادر على الاستفادة من الفهارس.
بنية قاعدة البيانات
tracks has_many artists
استعلام Non-Sargable
استخدام الدالة LOWER يمنع محرك نظام إدارة قواعد البيانات (DBMS) من الاستفادة من الفهارس.
Track.joins(:artists).where('LOWER(tracks.display_name) LIKE ?', "eric clapton%").explain
Gather (cost=1000.85..56714.32 width=4061)
Workers Planned: 2
-> Nested Loop (cost=0.85..55713.62 rows=3 width=4061)
-> Nested Loop (cost=0.42..55708.37 rows=3 width=4069)
-> Parallel Seq Scan on tracks (cost=0.00..55365.17 rows=41 width=4061)
Filter: (lower((display_name)::text) ~~* 'eric clapton%'::text)
-> Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations (cost=0.42..8.36 rows=1 width=16)
Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
-> Index Only Scan using idx_35952_primary on artists (cost=0.43..1.75 rows=1 width=8)
Index Cond: (id = artist_relations.artist_id)
استعلام Sargable
تتيح إزالة الدالة LOWER لمحرك DBMS استخدام الفهارس، مما يؤدي إلى تنفيذ أسرع.
Track.joins(:artists).where('tracks.display_name ILIKE ?', "eric clapton%").explain
Nested Loop (cost=1497.60..2695.43 width=4061)
-> Nested Loop (cost=1497.17..2684.94 rows=6 width=4069)
-> Bitmap Heap Scan on tracks (cost=1496.75..1873.05 rows=97 width=4061)
Recheck Cond: ((display_name)::text ~~* 'eric clapton%'::text)
-> Bitmap Index Scan on index_tracks_on_display_name (cost=0.00..1496.73 rows=97 width=0)
Index Cond: ((display_name)::text ~~* 'eric clapton%'::text)
-> Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations (cost=0.42..8.36 rows=1 width=16)
Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
-> Index Only Scan using idx_35952_primary on artists (cost=0.43..1.75 rows=1 width=8)
Index Cond: (id = artist_relations.artist_id)
الاستعلامات Sargable وNon-Sargable
الاستعلام sargable هو استعلام يمكنه استخدام فهرس لتسريع تنفيذه. فهو يسمح لمحرك DBMS بإجراء بحث في الفهرس (index seek)، وهو أسرع بكثير من مسح الجدول بأكمله. أما الاستعلام non-sargable فلا يمكنه استخدام الفهرس، لذا يكون أبطأ. ويأتي مصطلح sargable من عبارة "Search ARGument ABLE"، أي أن محرك DBMS يستطيع استخدام فهرس لتحسين الاستعلام. وفهم الفرق بين النوعين أساسي لتحسين أداء قاعدة البيانات.
الاستعلامات Non-Sargable
قد يكون للاستعلامات non-sargable أثر كبير في أداء الاستعلام، خاصة مع مجموعات البيانات الكبيرة. فعندما يكون الاستعلام non-sargable، يضطر محرك DBMS إلى إجراء مسح كامل للجدول أو مسح للفهرس، وكلاهما عملية ثقيلة. وقد يؤدي ذلك إلى بطء التنفيذ وارتفاع استهلاك المعالج وضعف أداء النظام عمومًا. لذا فإن اكتشاف الاستعلامات non-sargable وتحسينها أساسي لرفع كفاءة قاعدة البيانات وسرعة استجابتها.
الدوال في عبارة WHERE
قد يؤدي استخدام الدوال في عبارة WHERE إلى جعل الاستعلام non-sargable. ويحدث ذلك لأن محرك DBMS لا يستطيع استخدام فهرس لتحسين الاستعلام عند تطبيق دالة على عمود في عبارة WHERE. على سبيل المثال، لنأخذ الاستعلام SELECT FROM table WHERE UPPER(column) = 'VALUE'. هذا الاستعلام non-sargable لأن الدالة UPPER مطبقة على العمود، فلا يمكن استخدام الفهرس. ولجعله sargable، يمكنكم إزالة الدالة وإعادة كتابة الاستعلام على النحو التالي: SELECT FROM table WHERE column = 'VALUE'. عندها يستطيع محرك DBMS استخدام الفهرس ويصبح الاستعلام أسرع.
الفهارس وتحسين الاستعلامات
الفهارس عنصر أساسي في تحسين الاستعلامات، لأنها تتيح لمحرك DBMS العثور على البيانات بسرعة، وبالتالي تسريع الاستعلام. لكن لا يمكن استخدام الفهرس إلا إذا كان الاستعلام sargable. فإذا كان non-sargable، فلن يُستخدم الفهرس وسيكون الاستعلام أبطأ. لذا أنشئوا فهارس على الأعمدة المستخدمة في عبارة WHERE، وتأكدوا من أن استعلاماتكم sargable. سيحسّن ذلك أداء قاعدة بياناتكم بشكل كبير.
تحويل الشروط Non-Sargable
يُعد تحويل الشروط non-sargable إلى sargable خطوة من خطوات تحسين الاستعلامات. ويمكن تحويل الشرط non-sargable إلى sargable بإعادة كتابة الاستعلام لإزالة أي دوال أو عمليات تمنع استخدام الفهرس. على سبيل المثال، الاستعلام SELECT FROM table WHERE YEAR(date) = 2022 هو non-sargable لأن الدالة YEAR مطبقة على العمود date. ولجعله sargable، يمكنكم إعادة كتابته على النحو التالي: SELECT FROM table WHERE date >= '2022-01-01' AND date < '2023-01-01'. هذا الاستعلام المعاد كتابته sargable لأن محرك DBMS يستطيع استخدام فهرس على العمود date لتحسين الاستعلام، وسيكون أسرع.