استعلام FREETEXT بطيء - يشمل الأعلى والطلب بواسطة
-
02-10-2019 - |
سؤال
يحتوي جدول المنتج على 700 ألف سجل فيه. الاستعلام:
SELECT TOP 1 ID,
Name
FROM Product
WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
يستغرق حوالي دقيقة واحدة للركض. يوجد فهرس غير متكامل على فهرس DatemAdenew و Freetext على الاسم.
إذا قمت بإزالة أعلى 1 أو طلب - يستغرق الأمر أقل من ثانية واحدة للتشغيل.
هنا هو الرابط إلى خطة التنفيذ.http://screencast.com/t/zdczmzg5n
يبدو أن FullTextMatch لديه أكثر من 400 ألف عملية إعدام. لماذا يحدث هذا؟ كيف يمكن جعلها أسرع؟
تحديث 5/3/2010
يبدو أن Cardinality خارج عن عمليات البحث عن Freetext Multi Word:
يقدر المحسّن أن هناك 28 كيلو سجل مطابق "فستان أبيض" ، في حين أن هناك في الواقع واحد فقط.http://screencast.com/t/njm3zje4njat
إذا استبدلت "الفستان الأبيض" بـ "أبيض" ، فإن الرقم المقدر هو "27 ، 951" ، في حين أن الرقم الفعلي هو "28 ، 487" وهو أفضل بكثير.
يبدو أن Optimizer يستخدم الكلمة الأولى فقط في العبارة التي يتم البحث فيها عن العلب.
المحلول
يحرر
من http://technet.microsoft.com/en-us/library/cc721269.aspx#_toc202506240
أهم شيء هو أن نوع الصحيح يتم اختياره لاستعلام النص الكامل. يعد تقدير Cardinality على FullTextMatch STVF مهمًا جدًا للخطة الصحيحة. لذلك فإن أول شيء للتحقق هو تقدير Cardinality FulltextMatch. هذا هو العدد المقدر من الزيارات في الفهرس لسلسلة البحث النصية الكاملة. على سبيل المثال ، في الاستعلام في الشكل 3 ، يجب أن يكون هذا قريبًا من عدد المستندات التي تحتوي على مصطلح "الكلمة". في معظم الحالات ، يجب أن تكون دقيقة للغاية ، ولكن إذا كان التقدير قد تم إيقاف تشغيله ، فيمكنك توليد خطط سيئة. عادة ما يكون تقدير المصطلحات الفردية جيدًا للغاية ، ولكن تقدير مصطلحات متعددة مثل العبارات أو الاستعلامات أكثر تعقيدًا لأنه لا يمكن معرفة ما الذي سيعتمد تقاطع المصطلحات في الفهرس على تواتر المصطلحات في الفهرس . إذا كان تقدير Cardinality جيدًا ، فمن المحتمل أن يكون هناك خطة سيئة من طراز تكلفة مُحسّن الاستعلام. الطريقة الوحيدة لإصلاح مشكلة الخطة هي استخدام تلميح الاستعلام لإجبار نوع معين من الانضمام أو تحسينه.
لذلك لا يمكن أن تعرف ببساطة من المعلومات التي تخزنها ما إذا كان من المحتمل أن تكون مصطلحات البحث 2 معًا مستقلة تمامًا أو شائعة العثور عليها معًا. ربما يجب أن يكون لديك إجراءان منفصلان واحد لاستفسارات الكلمات المفردة التي تدعها المُحسّنة تقوم بأشياءها وإحدى الإجراءات المتعددة الكلمات التي تجبر خطة "جيدة بما يكفي" على (sys.dm_fts_index_keywords قد تساعد إذا كنت لا تريد a حجم واحد يناسب جميع الخطة).
NB: من المحتمل أن يحتاج إجراء كلمة واحدة إلى خيار إعادة الترسيب مع هذا الجزء من المقال.
في SQL Server 2008 Search Full Text ، لدينا القدرة على تغيير الخطة التي يتم إنشاؤها بناءً على تقدير Cardinality لمصطلح البحث المستخدم. إذا تم إصلاح خطة الاستعلام (كما هو الحال في استعلام محدد داخل إجراء مخزن) ، فإن هذه الخطوة لا تحدث. لذلك ، تخدم الخطة المترجمة هذا الاستعلام دائمًا ، حتى لو لم تكن هذه الخطة مثالية لمصطلح بحث معين.
الإجابة الأصلية
خطتك الجديدة لا تزال تبدو سيئة للغاية. يبدو أنه لا يعود سوى صف واحد من جزء الاستعلام الكامل للنص ولكن فحص جميع صفوف 770159 في جدول المنتج.
كيف يؤدي هذا؟
CREATE TABLE #tempResults
(
ID int primary key,
Name varchar(200),
DateMadeNew datetime
)
INSERT INTO #tempResults
SELECT
ID, Name, DateMadeNew
FROM Product
WHERE contains(Name, '"White Dress"')
SELECT TOP 1
*
FROM #tempResults
ORDER BY DateMadeNew desc
نصائح أخرى
لا يمكنني رؤية خطة التنفيذ المرتبطة ، وهي شرطة الشبكة تحجب ذلك ، لذلك هذا مجرد تخمين ...
إذا كان يعمل بسرعة بدون TOP
و ORDER BY
, ، حاول القيام بذلك:
SELECT TOP 1
*
FROM (SELECT
ID, Name, DateMadeNew
FROM Product
WHERE contains(Name, '"White Dress"')
) dt
ORDER BY DateMadeNew desc
يبدو أن FullTextMatch لديه أكثر من 400 ألف عملية إعدام. لماذا يحدث هذا؟
بما أن لديك فهرس مع TOP 1
, ، يعتقد Optimizer أنه سيكون من الأفضل اجتياز الفهرس ، والتحقق من كل سجل للإدخال.
كيف يمكن جعلها أسرع؟
إذا لم يساعد تحديث الإحصاءات ، فحاول إضافة تلميح إلى استعلامك:
SELECT TOP 1 *
FROM product pt
WHERE CONTAINS(name, '"test1"')
ORDER BY
datemadenew DESC
OPTION (HASH JOIN)
هذا سيجبر المحرك على استخدام أ HASH JOIN
خوارزمية للانضمام إلى الجدول الخاص بك وإخراج استعلام النص الكامل.
يعتبر استعلام النص الكامل مصدرًا عن بُعد يرجع مجموعة القيم التي تم فهرسها بواسطة KEY INDEX
منصوص عليه في FULLTEXT INDEX
تعريف.
تحديث:
إذا كان لديك ORM
يستخدم الاستعلامات المعلمة ، يمكنك إنشاء دليل خطة.
- استخدم profiler لاعتراض الاستعلام الذي
ORM
يرسل حرفي - إنشاء خطة صحيحة في
SSMS
باستخدام تلميحات وحفظها كـXML
- يستخدم
sp_create_plan_guide
مع الOPTION USE PLAN
لإجبار المحسن دائمًا على استخدام هذه الخطة.
واجهت نفس المشكلة في وقت سابق.
يعتمد الأداء على الفهرس الفريد الذي تختاره لفهرسة النص الكامل. يحتوي طاولتي على عمودين فريدان - ID
و article_number
.
الاستعلام:
select top 50 id, article_number, name, ...
from ARTICLE
CONTAINS(*,'"BLACK*" AND "WHITE*"')
ORDER BY ARTICLE_NUMBER
إذا كان فهرس النص الكامل متصلاً بـ ID
ثم يكون بطيئًا اعتمادًا على الكلمات التي تم تفتيشها. إذا كان فهرس النص الكامل متصلاً بـ ARTICLE_NUMBER UNIQUE
الفهرس ثم كان دائما سريعا.
لدي حل أفضل.
1. دعونا أولاً نظرة عامة على الحلول المقترحة حيث يمكن استخدامها أيضًا في بعض الحالات:
الخيار (Joinn Join) - ليس جيدًا لأنك قد تحصل على خطأ "لم يستطع معالج الاستعلام إنتاج خطة استعلام بسبب التلميحات المحددة في هذا الاستعلام. إعادة تقديم الاستعلام دون تحديد أي تلميحات ودون استخدام مجموعة القوة."
حدد ترتيب الأعلى 1 * من (Original_Select) بواسطة ... - ليس جيدًا ، عندما تحتاج إلى استخدام نتائج ترقيم التكرار منك Original_select
SP_CREATE_PLAN_GUIDE - ليس جيدًا ، لاستخدام Plan_Guide ، عليك حفظ الخطة لبيان SQL محدد ، لن يعمل هذا مع عبارات SQL الديناميكية (على سبيل المثال ، تم إنشاؤها بواسطة ORM)
الثاني. يحتوي حلي على جزأين 1. جدول انضمام ذاتي يستخدم للبحث عن النص الكامل 2. استخدم تلميحات تجزئة MS SQL MSDN انضم إلى تلميحات
SQL الخاص بك:
SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
يجب إعادة كتابتها على النحو التالي:
SELECT TOP 1 p.ID, p.Name FROM Product p INNER HASH JOIN Product fts ON fts.ID = p.ID
WHERE contains(fts.Name, '"White Dress"')
ORDER BY p.DateMadeNew desc
إذا كنت تستخدم nhibernate مع/بدون Castle Active Records ، فقد أجبت في بريد كيفية كتابة Interceptor لتعديل استعلامك لاستبدال Join Inner by Inner Hash Join
بعض الأفكار حول هذا:
1) هل قمت بتحديث الإحصائيات على جدول المنتج؟ سيكون من المفيد رؤية التقديرات والعدد الفعلي للصفوف على العمليات هناك أيضًا.
2) ما هو إصدار SQL Server الذي تستخدمه؟ لقد واجهت مشكلة مماثلة مع SQL Server 2008 والتي تبين أنها ليست أكثر من عدم تثبيت حزمة الخدمة 1. قم بتثبيت SP1 واستعلام Freetext الذي كان يستغرق بضع دقائق (بسبب عدد كبير من عمليات الإعدام الفعلية ضد الفعلي) انخفض لأخذ ثانية.