حدثت مشكلة أثناء محاولة فرض استخدام الفهرس الذي تمت تصفيته

dba.stackexchange https://dba.stackexchange.com/questions/106365

سؤال

كنت أحاول إجراء بعض الاختبارات على الفهارس التي تمت تصفيتها بالأمس وخلقت موقفًا بسيطًا إلى حد ما:

CREATE TABLE IndexTest 
(
    ID INT NOT NULL IDENTITY(1,1) CONSTRAINT pk_IndexTest PRIMARY KEY, 
    Col1 CHAR(1)
)
GO

CREATE INDEX ix_IndexTest ON IndexTest(Col1)
WHERE Col1 IS NOT NULL
GO

INSERT INTO IndexTest VALUES ('A'),('B'),('C'),('D')
INSERT INTO IndexTest VALUES (''),(''),(''),('')
INSERT INTO IndexTest VALUES (NULL),(NULL),(NULL),(NULL)
GO

ثم حاولت بعد ذلك تشغيل الاستعلام التالي باستخدام تلميح لإجباره على استخدام الفهرس الذي تمت تصفيته.

SELECT * 
FROM IndexTest WITH (INDEX(ix_IndexTest))
GO

لكنني أستمر في الحصول على الخطأ:

تعذر على معالج الاستعلام إنتاج خطة استعلام بسبب التلميحات المحددة في هذا الاستعلام.قم بإعادة إرسال الاستعلام دون تحديد أي تلميحات ودون استخدام SET FORCEPLAN.

إنه يعمل إذا قمت بإزالة الفلتر ولكن ليس معه.حتى أنني حاولت تغيير الفلتر بطرق مختلفة مثل WHERE Col1 = '' إلخ.في أي وقت لدي مرشح أحصل على هذا الخطأ.يمكن لأحد أن يقول لي لماذا؟أفعل شيئا خاطئا؟

لقد جربت ذلك على مثيل SQL Server 2012 و2014 وأنشأت ملف sqlfiddle منه هنا:

http://www.sqlfiddle.com/#!6/4a850/1

يحرر: لست متأكدًا من أن الأمر مهم ولكن على وجه التحديد كنت أحاول معرفة ما إذا كان بإمكاني رؤية الصفوف التي يحتوي عليها الفهرس بالفعل.جاءت الفكرة من رؤية شخص ما يستخدم هذه التقنية لاستعادة البيانات (باستخدام فهرس غير مفلتر) من جدول تالف.

هل كانت مفيدة؟

المحلول

من المحتمل أن يكون سبب قطع الاتصال هو أن الفهرس الذي تمت تصفيته لن يقوم تلقائيًا بتصفية النتائج نيابةً عنك - يجب عليك كتابة عبارة WHERE التي تطابق مسند عامل التصفية الخاص بالفهرس حتى تتمكن من استخدام الفهرس.

وبعبارة أخرى، إذا كنت تحاول فقط الحصول على الصفوف WHERE Col1 IS NOT NULL, ، مازلت بحاجة إلى WHERE جملة للحد من الصفوف.إذا لم يتمكن SQL Server من استخدام الفهرس الذي تحاول فرضه لتلبية جميع الصفوف التي سيتم إرجاعها بواسطة الاستعلام، وهو ما لا يمكنه فعله من خلال تعريف الفهرس الذي يحتوي على صفوف أقل (أو نفس *) من الجدول، لا يمكن تشغيله.

* قد تكون هناك سيناريوهات لم أختبرها بعد حيث سينجح هذا الأمر؛على سبيل المثال، إذا كان العمود مقيدًا بـ NOT NULL (أو تتطابق جميع الصفوف مع مسند عامل التصفية)، فإن الفهرس الذي تمت تصفيته، بالامتداد، يمثل صفوفًا من الجدول بأكمله.لكن هذا سيناريو مفتعل وغير عملي (حتى لو نجح).وتعذر على SQL Server إنشاء خطة للحالة التي تتطابق فيها جميع الصفوف حاليًا مع عامل التصفية، لأن إدراجًا أو تحديثًا واحدًا قد يؤدي إلى تعطيلها.

إذا كنت تحاول تحديد موقع البيانات من الفهرس غير المجمع بسبب تلف الجدول/CI الأساسي، فمن المحتمل أن يكون حظك أفضل مع DBCC IND/PAGE أو مع انتحال شخصية بول راندال الذي يستخدم محررًا سداسيًا.

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