Test veritabanımda 250K satır içeren bir tablo var. (Üretimde birkaç yüz milyon var, aynı sorunu orada gözlemleyebiliriz.) Tabloda nullchar2 (50) dize tanımlayıcısı var, boş değil, üzerinde benzersiz bir dizin var (PK değil).
Tanımlayıcılar, test veritabanımda (ve üretimde yaklaşık bin) 8 farklı değere sahip bir ilk bölümden, sonra bir @ işaretinden ve son olarak da 1 ila 6 basamak uzunluğunda bir sayıdan oluşur. Örneğin, 'ABCD_BGX1741F_2006_13_20110808.xml @' ile başlayan 50 bin satır olabilir ve bunu 50 bin farklı sayı izler.
Tanımlayıcısına bağlı olarak tek bir satırı sorguladığımda, kardinalite 1 olarak tahmin ediliyor, maliyet çok düşük, iyi çalışıyor. Bir IN ifadesinde veya OR ifadesinde birden fazla tanımlayıcı içeren birden fazla satırı sorguladığımda, dizin için tahminler tamamen yanlış, bu nedenle tam tablo taraması kullanılıyor. Dizini bir ipucu ile zorlarsam, çok hızlıdır, tam tablo taraması aslında daha yavaş bir büyüklükte (ve üretimde çok daha yavaş) gerçekleştirilir. Bu yüzden bir optimizer problemidir.
Bir test olarak, aynı DDL ve tam olarak aynı içeriğe sahip tabloyu (aynı şema + tablo alanında) çoğalttım. İyi ölçmek için ilk tablodaki benzersiz dizini yeniden oluşturdum ve aynı dizini klon tablosunda oluşturdum. Ben yaptım DBMS_STATS.GATHER_SCHEMA_STATS('schemaname',estimate_percent=>100,cascade=>true);
. Hatta dizin adlarının ardışık olduğunu görebilirsiniz. Bu yüzden şimdi iki tablo arasındaki tek fark, birincinin uzun bir süre boyunca rastgele sırada yüklenmesi, blokların diske dağılmış olması (diğer birkaç büyük tablo ile birlikte bir tablo alanında), ikincisinin toplu olarak yüklenmesi INSERT- SEÇ. Bunun dışında hiçbir fark düşünemiyorum. (Orijinal tablo son büyük silme işleminden bu yana küçüldü ve bundan sonra tek bir silme olmadı.)
İşte hasta ve klon tablosu için sorgu planları (Siyah fırçanın altındaki teller resmin her tarafında ve gri fırçanın altında aynıdır.):
(Bu örnekte, siyah fırçalanmış tanımlayıcıyla başlayan 1867 satır vardır. 2 satırlı sorgu 1867 * 2 kardinalitesi, 3 satırlı sorgu 1867 * 3 kardinalitesi üretir, vb. tesadüf olarak, Oracle tanımlayıcıların sonunu umursamıyor gibi görünüyor.)
Bu davranışa ne sebep olabilir? Tabii üretimde tabloyu yeniden oluşturmak oldukça pahalı olurdu.
USER_TABLES: http://i.stack.imgur.com/nDWze.jpg USER_INDEXES: http://i.stack.imgur.com/DG9um.jpg Yalnızca şema ve tablo alanı adını değiştirdim. Tablo ve dizin adlarının sorgu planı ekran görüntüsüyle aynı olduğunu görebilirsiniz.