Sybase - فشل في استخدام الفهرس ما لم تكن السلسلة مشفرة صلبة

StackOverflow https://stackoverflow.com/questions/2501825

سؤال

أنا استخدم Sybase 12.5.3 (ASE); ؛ أنا جديد على Sybase على الرغم من أنني عملت مع MSSQL على نطاق واسع. أنا أواجه سيناريو يكون فيه الإجراء المخزن بطيئًا جدًا. لقد تتبعت المشكلة إلى STMT SELECT لجدول كبير نسبيًا. تعديل هذا البيان يحسن بشكل كبير أداء الإجراء (وعودةه يبطئه بشكل كبير ؛ أي أن SELECT STMT هو بالتأكيد الجاني).

-- Sybase optimizes and uses multi-column index... fast!<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in ('NEW','SENT')
ORDER BY ID

-- Sybase does not use index and does very slow table scan<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in (select status from allowableStatusValues)
ORDER BY ID

الكود أعلاه هو نسخة مكيفة/مبسطة من الكود الفعلي. لاحظ أنني حاولت بالفعل إعادة تجميع الإجراء ، وتحديث الإحصاءات ، إلخ.

ليس لدي أي فكرة عن سبب اختيار Sybase ASE فهرسًا فقط عندما تكون الأوتار مرمزة صلابة واختيار فحص الجدول عند الاختيار من جدول آخر. شخص ما من فضلك أعطني فكرة ، وشكرا لك مقدمًا.

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

المحلول

1. القضية هنا هي الترميز الضعيف. في إصدارك ، يعتبر الرمز الضعيف وتصميم الجدول السيئ هو الأسباب الرئيسية (98 ٪) ، ويتخذ المحسن قرارات غير صحيحة (يسير الاثنان جنبًا إلى جنب ، لم أحسب نسبة كل منهما). كلاهما:

    WHERE status IN ('NEW','SENT')

و

    WHERE status IN (SELECT status FROM allowableStatusValues)

هي دون المستوى المطلوب ، لأنها في كلتا الحالتين تتسبب في إنشاء ASE لإنشاء محتويات للمحتويات بين الأقواس ، والتي يمكن تجنبها بسهولة (وجميع المشكلات التبعية التي تم تجنبها). لا توجد إمكانية لإحصائيات على قابلية العمل ، لأن الإحصائيات على T.Status أو S.Status مفقودة (Adamh صحيحة في تلك النقطة) ، فإنها تختار بشكل صحيح فحص الجدول.

الغزوات الفرعية لها مكانها ، ولكن ليس كبديل لنقي (الجداول نكون ذات الصلة) الانضمام. التصحيحات هي:

    WHERE status = "NEW" OR status = "SENT"

و

    FROM  myTable t,
          allowableStatusValues s
    WHERE t.status = s.status

2. البيان

|الآن ليس عليك إضافة فهرس للحصول على إحصائيات على عمود ، ولكن ربما تكون أفضل طريقة.

غير صحيح. لا تنشئ أبدًا مؤشرات لن تستخدمها. إذا كنت تريد تحديث إحصائيات على عمود

    UPDATE STATISTICS myTable (status)

3. من المهم التأكد من أن لديك إحصائيات حالية على (أ) جميع الأعمدة المفهرسة و (ب) جميع الأعمدة.

4. نعم ، لا يوجد بديل لـ Showplan على كل قطاع رمز مخصص للإصدار ، بشكل مضاعف لأي رمز بأداء مشكوك فيه. يمكنك أيضا SET NOEXEC ON, ، لتجنب التنفيذ ، على سبيل المثال. لمجموعات النتائج الكبيرة.

نصائح أخرى

ستعمل تلميح الفهرس حوله ، ولكن ربما لا يكون الحل.

أولاً ، أود أن أعرف ما إذا كان هناك فهرس على lemtablestatusvalues.status ، إذا كان هناك ، فسيحتوي Sybase على إحصائيات عليه وسيكون له فكرة جيدة عن عدد القيم الموجودة هناك. إذا لم يكن الأمر كذلك ، فلن يكون لدى المحسن فكرة جيدة عن عدد حالة القيم المختلفة. بعد ذلك ، يجب أن تفترض أنك ستستخرج جميع الصفوف تقريبًا من Mytable ، وأفضل طريقة للقيام بذلك هي مسح الجدول (إذا لم يكن هناك فهرس تغطية).

الآن لا يتعين عليك إضافة فهرس للحصول على إحصائيات على عمود ، ولكن من المحتمل أن يكون هذا هو أفضل طريقة.

إذا كان لديك فهرس على lemtablestatusvalues.status ، فأتساءل عن مدى جودة إحصائياتك. احصل على نسخة من sp__optdiag. ربما تحتاج أيضًا إلى ضبط قيم "عامل ضبط الرسم البياني" و "عدد خطوات الرسم البياني" ، مما يزيد من ذلك قليلاً من الإعدادات الافتراضية سيمنحك إحصائيات أكثر تفصيلاً تساعد دائمًا على المحسن.

هل ما زال يقوم بإجراء فحص الجدول إذا استبدلت الاسم الفرعي بالانضمام:

SELECT m.ID,m.status,m.dateTime 
FROM myTable m
JOIN allowableStatusValues a on m.status = a.status
ORDER BY ID 

بدلاً من الاعتماد على الملاحظات التجريبية حول المدة التي يستغرقها الاستعلام ، أوصي بشدة بالحصول على Sybase لتظهر لك خطط التنفيذ لكل استعلام ، على سبيل المثال:

SET showplan ON
GO

-- query/procedure call goes here
SELECT id, status, datetime
FROM myTable
WHERE status IN('NEW','SENT')
ORDER BY id
GO

SET showplan OFF
GO

مع SET showplan ON, ، يقوم Sybase بإنشاء خطط تنفيذ لكل عبارة تنفذها. يمكن أن تكون هذه لا تقدر بثمن في المساعدة في تحديد مكان عدم استخدام الاستعلامات من الفهارس المناسبة. بالنسبة للإجراءات المخزنة في Sybase ، يتم إنشاء خطة التنفيذ للإجراء بأكمله عند تنفيذ الإجراء المخزن لأول مرة بعد تجميعه.

إذا قمت بنشر الخطط لكل من استفساراتك ، فقد نتمكن من إلقاء المزيد من الضوء على المشكلة.

بشكل مثير للدهشة ، باستخدام فهرس تلميح يحل المشكلة (انظر (فهرس myindexname) السطر أدناه - رمز إعادة كتابة/مبسطة أدناه:

-- using INDEX HINT
SELECT ID,status,dateTime 
FROM myTable (index myIndexName)
WHERE status in (select status from allowableStatusValues) 
ORDER BY ID 

غريب أنني لديك لاستخدام هذه التقنية لتجنب فحص الجدول ، ولكن هناك تذهب.

غاريت ، من خلال إظهار الكود المبسط فقط ، من المحتمل أن تكون قد قامت بتجريد المعلومات التي من شأنها أن تضيء مصدر المشكلة.

سيكون تخميني الأول هو عدم التوافق بين المسموح به. status و mytable.status. ومع ذلك ، هذا ليس الاحتمال الوحيد. كما ذكر Ninesed ، فإن خطط الاستعلام الكاملة (باستخدام أعلام Showplan و FMTONLY) ، وكذلك تعريفات الجدول الفعلية ومصدر الإجراء المخزن ، من المرجح أن تنتج إجابة مفيدة.

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