Birincil anahtarda kendi kendine katılma


9

NKendi kendine birleşmelerden oluşan bu sorguyu düşünün :

select
    t1.*
from [Table] as t1
join [Table] as t2 on
    t1.Id = t2.Id
-- ...
join [Table] as tN on
    t1.Id = tN.Id

N kümelenmiş dizin taramaları ve N-1 birleştirme birleşimleriyle bir yürütme planı oluşturur.

Dürüst olmak gerekirse, tüm birleşimleri optimize etmek ve sadece bir kümelenmiş dizin taraması yapmak için herhangi bir neden görmüyorum, yani orijinal sorguyu buna göre optimize edin:

select
    t1.*
from [Table] as t1

Sorular

  • Birleştirmeler neden optimize edilmiyor?
  • Her birleştirmenin sonuç kümesini değiştirmediğini söylemek matematiksel olarak yanlış mıdır?

Test tarihi:

  • Kaynak Sunucu Sürümü: SQL Server 2014 (12.0.4213)
  • Kaynak Veritabanı Altyapısı Sürümü: Microsoft SQL Server Standard Edition
  • Kaynak Veritabanı Motor Türü: Standalone SQL Server
  • Uyumluluk seviyesi: SQL Server 2008 (100)

Sorgu anlamlı değil; aklıma geldi ve şimdi merak ediyorum.

İşte tablo oluşturma ve 3 sorgu ile keman : ile inner join's, ile left join' ve karışık. Ayrıca burada icra planına da bakabilirsiniz.

Görünüşe göre left joins değilken sonuç yürütme planında inner joins elenir . Yine de nedenini anlamıyorum .

Yanıtlar:


18

İlk olarak, (id)tablonun birincil anahtarı olduğunu varsayalım . Bu durumda, evet, birleşimler gereksizdir (kanıtlanabilir) ve ortadan kaldırılabilir.

Şimdi bu sadece teori - ya da matematik. Optimize edicinin gerçek bir eliminasyon yapabilmesi için teorinin koda dönüştürülmesi ve optimize edicinin optimizasyon / yeniden yazma / ortadan kaldırma paketine eklenmesi gerekir. Bunun gerçekleşmesi için, (DBMS) geliştiricileri, verimliliğe iyi fayda sağlayacağını ve bunun yeterince yaygın bir durum olduğunu düşünmelidir.

Şahsen, kulağa benzemiyor (yeterince yaygın). Sorgu - kabul ettiğiniz gibi - oldukça aptalca görünüyor ve bir geliştirici, iyileştirilmedikçe ve gereksiz katılım kaldırılmadığı sürece incelemeyi geçmesine izin vermemelidir.

Bununla birlikte, eliminasyonun gerçekleştiği benzer sorgular var. Rob Farley: SQL Server'da JOIN basitleştirmesi ile ilgili çok güzel bir blog yazısı var .

Bizim durumumuzda, birleştirmeleri birleştirmek için tek yapmamız gereken LEFT. Bkz. Dbfiddle.uk . Bu durumda optimize edici, birleştirmenin sonuçları muhtemelen değiştirmeden güvenle kaldırılabileceğini bilir. (Sadeleştirme mantığı oldukça geneldir ve kendiliğinden birleşmeler için özel kasalı değildir.)

Tabii ki orijinal sorguda, INNERbirleştirmeleri kaldırmak da sonuçları değiştiremez. Ancak birincil anahtarda kendi kendine katılmak hiç de yaygın değildir, bu nedenle optimize edicide bu durum uygulanmaz. Bununla birlikte, birleştirilmiş sütunun tablolardan birinin birincil anahtarı olduğu (ve genellikle bir yabancı anahtar kısıtlaması olduğu) katılmak (veya sol birleşmek) yaygındır. Bu, birleştirmeleri ortadan kaldırmak için ikinci bir seçeneğe yol açar: (Kendinden referanslı!) Bir yabancı anahtar kısıtlaması ekleyin:

ALTER TABLE "Table"
    ADD FOREIGN KEY (id) REFERENCES "Table" (id) ;

Ve voila, birleşimler elendi! (aynı kemanda test edilmiştir): burada

create table docs
(id int identity primary key,
 doc varchar(64)
) ;
GO
insert
into docs (doc)
values ('Enter one batch per field, don''t use ''GO''')
     , ('Fields grow as you type')
     , ('Use the [+] buttons to add more')
     , ('See examples below for advanced usage')
  ;
GO
4 satır etkilenir
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    join docs d2 on d2.id=d1.id
    join docs d3 on d3.id=d1.id
    join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | doktor                                      
-: | : ----------------------------------------
 1 | Alan başına bir parti girin, 'GO' kullanmayın
 2 | Alanlar siz yazdıkça büyür                  
 3 | Daha fazla eklemek için [+] düğmelerini kullanın          
 4 | Gelişmiş kullanım için aşağıdaki örneklere bakın    

resim açıklamasını buraya girin

--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    left join docs d2 on d2.id=d1.id
    left join docs d3 on d3.id=d1.id
    left join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | doktor                                      
-: | : ----------------------------------------
 1 | Alan başına bir parti girin, 'GO' kullanmayın
 2 | Alanlar siz yazdıkça büyür                  
 3 | Daha fazla eklemek için [+] düğmelerini kullanın          
 4 | Gelişmiş kullanım için aşağıdaki örneklere bakın    

resim açıklamasını buraya girin

alter table docs
  add foreign key (id) references docs (id) ;
GO
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    join docs d2 on d2.id=d1.id
    join docs d3 on d3.id=d1.id
    join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | doktor                                      
-: | : ----------------------------------------
 1 | Alan başına bir parti girin, 'GO' kullanmayın
 2 | Alanlar siz yazdıkça büyür                  
 3 | Daha fazla eklemek için [+] düğmelerini kullanın          
 4 | Gelişmiş kullanım için aşağıdaki örneklere bakın    

resim açıklamasını buraya girin


2

İlişkisel olarak, öznitelik yeniden adlandırma olmadan herhangi bir kendi kendine katılım bir işlem değildir ve yürütme planlarından güvenle çıkarılabilir. Ne yazık ki SQL ilişkisel değildir ve kendi kendine birleştirme optimize edici tarafından ortadan kaldırılabilir durum az sayıda kenar durumu ile sınırlıdır.

SQL'in SELECT sözdizimi projeksiyona göre birleştirme mantıksal önceliği verir. SQL'in sütun adları için kapsam belirleme kuralları ve yinelenen sütun adlarına ve adlandırılmamış sütunlara izin verilmesi, SQL sorgu optimizasyonunu ilişkisel cebirin optimizasyonundan önemli ölçüde zorlaştırır. SQL DBMS satıcılarının sınırlı kaynakları vardır ve hangi optimizasyon türlerini desteklemek istedikleri konusunda seçici olmaları gerekir.


1

Birincil Anahtarlar her zaman benzersizdir ve boş değerlere izin verilmez, bu nedenle birincil anahtarlarda (kendiliğinden başvuru yapan bir ikincil anahtarla değil ve burada deyimler olmadan) bir tabloya birleştirmek orijinal tabloyla aynı sayıda satır üretecektir.

Neden onu optimize etmediklerine gelince, bunun ya planlamadığı ya da insanların yapamayacağı varsayılan bir durum olduğunu söyleyebilirim. Garantili benzersiz birincil anahtarlarda bir tabloya katılmak bir amaca hizmet etmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.