سؤال

يحتوي جدول المنتج على 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. دعونا أولاً نظرة عامة على الحلول المقترحة حيث يمكن استخدامها أيضًا في بعض الحالات:

  1. الخيار (Joinn Join) - ليس جيدًا لأنك قد تحصل على خطأ "لم يستطع معالج الاستعلام إنتاج خطة استعلام بسبب التلميحات المحددة في هذا الاستعلام. إعادة تقديم الاستعلام دون تحديد أي تلميحات ودون استخدام مجموعة القوة."

  2. حدد ترتيب الأعلى 1 * من (Original_Select) بواسطة ... - ليس جيدًا ، عندما تحتاج إلى استخدام نتائج ترقيم التكرار منك Original_select

  3. 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 الذي كان يستغرق بضع دقائق (بسبب عدد كبير من عمليات الإعدام الفعلية ضد الفعلي) انخفض لأخذ ثانية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top