2016-03-29 16 views
2

Yürütmek için çok uzun süren aşağıdaki sorgun var (yaklaşık 30 saniye). Bu sorguyu optimize etmenin herhangi bir yolu var mı yoksa izin vermeli miyim?MySQL Sorgu en iyileştirme yardım gerekli

SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name 
FROM db.vehicle_part k 
JOIN db.vehicle l ON k.ID_Vehicle = l.ID 
JOIN db.part m ON k.ID_Part = m.ID 

JOIN db.part_generic_part b ON b.ID_Part = m.ID 
JOIN db.generic_part c ON c.ID = b.ID_Generic_part 
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part 
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part 
JOIN db.part_category f ON e.ID_category = f.ID 
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category 
JOIN db.lang h ON g.ID_Lang = h.ID 

WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2 
+0

Belki dizinlerden başlayabilirsiniz. – Nitish

+0

Bu, bir sorunun açıklaması değil, yalnızca birkaç sayı ve bir SQL sorgusudur. Veritabanının şeması nedir (tabloların yapısı - indeksler dahil - ve bunlar arasındaki bağlantılar), tahmini yürütme planı nedir, kayıt sayısı nedir? Bir sorguyu optimize etmek, yalnızca bazı en iyi uygulamaları uygulamakla kalmaz, aynı zamanda üzerinde çalıştığınız verilerin de bilinmesini gerektirir. Verileriniz hakkında hiçbir şey bilmiyoruz. Verilerini biliyor musun? Bize öğretebilir misin? – Pred

cevap

0

@Gordon Linoff'un işaret ettiği gibi, dizinleri tanımlamanız gerekir. Ancak, sorgunuzla daha fazla iş yapmak için bazı şeyler var. Bu sıra tabloları sırasını tanımlamak için kesinlikle daha iyi, bu yüzden bu garantisi yoktur rağmen daha şık bir koddur bu

SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name 
FROM db.vehicle_part k 
JOIN db.vehicle l ON k.ID_Vehicle = l.ID 
JOIN db.part m ON k.ID_Part = m.ID 

JOIN db.part_generic_part b ON b.ID_Part = m.ID 
JOIN db.generic_part c ON c.ID = b.ID_Generic_part 
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part 
JOIN db.part_category f ON e.ID_category = f.ID 
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category 
JOIN db.lang h ON g.ID_Lang = h.ID 
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part 

WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2 

bu

SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name 
FROM db.vehicle_part k 
JOIN db.vehicle l ON k.ID_Vehicle = l.ID 
JOIN db.part m ON k.ID_Part = m.ID 

JOIN db.part_generic_part b ON b.ID_Part = m.ID 
JOIN db.generic_part c ON c.ID = b.ID_Generic_part 
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part 
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part 
JOIN db.part_category f ON e.ID_category = f.ID 
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category 
JOIN db.lang h ON g.ID_Lang = h.ID 

WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2 

değiştirmek aslında olacak ilk olandan daha hızlı olun. Ancak, bu daha iyi düzen ile, bir sonraki adıma geçiyoruz. where yan tümcesi, join tamamlandığında, belleğe yüklenen büyük, çok boyutlu bir kayıt kümesine sahip olduğunuzdan ve satırları filtrelediğinizden sonra yürütülür. on durum daha erken çalıştırır, dolayısıyla bir sonraki adım, bu gibi where değiştirmek ve on koşulları içine durumunu taşımaktır:

SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name 
FROM db.vehicle_part k 
JOIN db.vehicle l ON k.ID_Vehicle = l.ID AND l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' 
JOIN db.part m ON k.ID_Part = m.ID 

JOIN db.part_generic_part b ON b.ID_Part = m.ID 
JOIN db.generic_part c ON c.ID = b.ID_Generic_part 
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part 
JOIN db.part_category f ON e.ID_category = f.ID 
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category and g.ID_Lang =2 
JOIN db.lang h ON g.ID_Lang = h.ID 
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part 

Bu şekilde, gereksiz kayıtları onlar beri zamanı azaltarak, join ğine filtrelenir hepsi belleğe yüklenmez ve ardından filtrelenir. Son adım, eğer ve ancak sorgu hala yavaşsa, kodun okunabilirliğini azalttığından, yapılmalıdır: Şiddetli bir filtreye sahip olan (satır sayısını önemli ölçüde azaltan) veya ciddi bir projeksiyona sahip olan (çok sayıda) join Büyük alanlar, ancak adlandırılmış alt-seçimlere, bunun sadece küçük bir alt kümesine ihtiyaç vardı. Örnek:

SELECT 'BMW', '3 (E30)', '316 i', m.ID, g.Name 
from (select temp.ID from db.vehicle temp where temp.Name = 'BMW' AND temp.Model = '3 (E30)' AND temp.Engine_Type= '316 i') l 
JOIN db.vehicle_part k on l.ID = k.ID_VEHICLE 
JOIN db.part m ON k.ID_Part = m.ID 

JOIN db.part_generic_part b ON b.ID_Part = m.ID 
JOIN db.generic_part c ON c.ID = b.ID_Generic_part 
JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part 
JOIN db.part_category f ON e.ID_category = f.ID 
JOIN db.part_category_name g ON f.ID = g.ID_Part_Category and g.ID_Lang =2 
JOIN db.lang h ON g.ID_Lang = h.ID 
JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part 

Bu son değişiklik ön filtreler l ile join başlatmak için kayıtların sadece bir avuç olmadığından emin olmak için.

+0

Bu, bir sürü waffle'a benziyor. Burada yapılan ifadelerden herhangi birini destekleyen herhangi bir veri var mı? – Strawberry

+0

Değişikliklerin bazıları yürütme planı üzerinde bazı etkiye sahip olabilir, ancak verilerin dağılımına, dizinlere, dizinlerin yapısına vb. Bağlıdır. Yine, veritabanıyla ilgili gerçekleri bilmeden, bu sadece tahmin . Tüm tabloların gerekli olup olmadığından bile emin değilim (yine, bu ifadenin gerçekleri bilmediğimiz anahtar ve sütun özelliklerine bağlıdır). – Pred

+0

Şüphesiz, açık, kayıtlar birleştirildiğinde tam olarak çalıştırılan bir yerdir. Nerede (birleşmelerle birlikte) zaten yürütüldüğünü varsayar. Birkaç RDBMS'de birkaç kaynak vardır (http://stackoverflow.com/questions/10133356/where-clause-before-inner-join ve https://msdn.microsoft.com/en-us/library/ms189499.aspx) Bu konuda ve benim deneylerim de bunu doğruladı.Subselect, gerçekten mysql'i birleştirilmeden önce bir tablodan satırları filtrelemeye zorlar ve her filtrelenmiş kayıt yalnızca bir kez –

2

Katılanlar için kullanılan tüm sütunlarda dizinler olmalıdır.

db_vehicle(name, model, engine_type, id) 

Bu

where maddesinin kullanılması gerektiğini ve sorguyu hızlandırmak: Daha da önemlisi, db.vehicle üzerinde bir dizin olmalıdır.