MySQL birden fazla sorguyu tek bir sorguda sorgular. MySQL Sorgularını Optimize Etme

Geçen derste bir sıkıntıyla karşılaştık. “Bisikletler” konusunu kimin oluşturduğunu öğrenmek istediğimizde buna uygun bir talepte bulunduk:

Yazarın adı yerine kimliğini aldık. Bu anlaşılabilir bir durumdur, çünkü bir tabloya (Konular) sorgu yaptık ve konu yazarlarının adları başka bir tabloda (Kullanıcılar) saklandı. Bu nedenle, konu yazarının tanımlayıcısını bulduktan sonra, adını bulmak için Kullanıcılar tablosuna başka bir sorgu yapmamız gerekir:

SQL, bu sorgulardan birini bir alt sorguya (iç içe sorgu) dönüştürerek bu tür sorguları tek bir sorguda birleştirme olanağı sağlar. Dolayısıyla "bisikletler" konusunu kimin oluşturduğunu bulmak için aşağıdaki sorguyu yapacağız:

Yani, anahtar kelimeden sonra NEREDE, koşula başka bir istek yazıyoruz. MySQL önce alt sorguyu işler, id_author=2 değerini döndürür ve bu değer yan tümceye iletilir NEREDE harici istek.

Bir sorguda birden fazla alt sorgu olabilir, böyle bir sorgunun sözdizimi aşağıdaki gibidir: Alt sorguların yalnızca bir sütunu seçebileceğini ve bunların değerlerini dış sorguya döndüreceklerini unutmayın. Birden fazla sütun seçmeye çalışmak hatayla sonuçlanacaktır.

Bunu pekiştirmek için başka bir istekte bulunalım ve "bisikletler" konusunun yazarının forumda hangi mesajları bıraktığını öğrenelim:

Şimdi görevi karmaşıklaştıralım, "bisikletler" konusunun yazarının hangi konularda mesaj bıraktığını öğrenelim:

Nasıl çalıştığını anlayalım.

  • MySQL ilk olarak en derin sorguyu yürütecektir:

  • Ortaya çıkan sonuç (id_author=2), şu formu alacak harici bir isteğe iletilecektir:

  • Ortaya çıkan sonuç (id_topic:4,1), şu formu alacak harici bir isteğe iletilecektir:

  • Ve nihai sonucu verecektir (konu_adı: balık tutma hakkında, balık tutma hakkında). Onlar. "Bisikletler" konusunun yazarı, Sergei tarafından oluşturulan "Balıkçılık hakkında" konusuna (id=1) ve Sveta tarafından oluşturulan "Balıkçılık hakkında" konusuna (id=4) mesaj bıraktı.
İç içe sorgular hakkında söylemek istediklerim bu kadar. Ancak dikkat edilmesi gereken iki nokta var:
  • Üçten büyük iç içe geçme derecesine sahip sorguların oluşturulması önerilmez. Bu, yürütme süresinin artmasına ve kodu anlamanın zorlaşmasına yol açar.
  • İç içe geçmiş sorgular için verilen sözdizimi muhtemelen en yaygın olanıdır, ancak tek olan bu değildir. Örneğin, sormak yerine

    yazmak

    Onlar. kullanılan herhangi bir operatörü kullanabiliriz anahtar kelime NEREDE (son derste bunları inceledik).

Zaten çok çeşitli SQL sorguları hakkında yazdım, ancak artık daha karmaşık şeylerden bahsetmenin zamanı geldi, örneğin birkaç tablodan kayıtları seçmek için bir SQL sorgusu.

Sen ve ben bir tablodan seçim yaptığımızda her şey çok basitti:

tablo_adı NEREDEN seçim_koşulundan gerekli_alanların adlarını SEÇİN

Her şey çok basit ve önemsizdir, ancak birkaç tablodan aynı anda numune alırken durum biraz daha karmaşık hale gelir. Zorluklardan biri alan adlarının eşleştirilmesidir. Örneğin her tablonun bir kimlik alanı vardır.

Bu sorguya bakalım:

SELECT * FROM table_1, table_2 NEREDE table_1.id > table_2.user_id

Bu tür sorgularla uğraşmamış birçok kişi, alan adlarının önüne yalnızca tablo adlarının eklendiğini düşünerek her şeyin çok basit olduğunu düşünecektir. Aslında bu, aynı alan adları arasındaki çakışmaları önler. Ancak zorluk bunda değil, böyle bir SQL sorgusunun algoritmasında yatmaktadır.

Çalışma algoritması şu şekildedir: İlk kayıt tablo_1'den alınır. Bu kaydın kimliği tablo_1'den alınmıştır. Daha sonra table_2 tablosu tamamen görünüyor. Ve user_id alanının değerinin table_1'de seçilen kaydın kimliğinden küçük olduğu tüm kayıtlar eklenir. Böylece, ilk yinelemeden sonra 0'dan sonsuz sayıda sonuç kaydı olabilir. Bir sonraki yinelemede tablo_1 tablosunun bir sonraki kaydı alınır. table_2 tablosunun tamamı yeniden taranır ve table_1.id > table_2.user_id seçim koşulu yeniden tetiklenir. Bu koşulu karşılayan tüm kayıtlar sonuca eklenir. Çıktı, her iki tablonun toplam boyutundan kat kat daha büyük, çok sayıda kayıt olabilir.

İlk seferden sonra nasıl çalıştığını anlarsanız harika olur, ancak anlamadıysanız, tamamen anlayana kadar okuyun. Bunu anlarsanız işiniz daha kolay olacaktır.

Önceki SQL sorgusu bu nedenle nadiren kullanılır. Basitçe çoklu tablo örnekleme algoritmasını açıklamak için verilmiştir. Şimdi daha bodur bir SQL sorgusuna bakalım. Diyelim ki iki tablomuz var: ürünlerle (ürünün sahibinin kimliğinden sorumlu birowner_id alanı var) ve kullanıcılarla (bir kimlik alanı var). Tüm kayıtları tek bir SQL sorgusunda almak istiyoruz ve her biri kullanıcı ve onun ürünü hakkında bilgi içeriyor. Bir sonraki giriş aynı kullanıcı ve onun bir sonraki ürünü hakkında bilgi içeriyordu. Bu kullanıcının ürünleri bittiğinde bir sonraki kullanıcıya geçin. Bu nedenle, iki tabloyu birleştirmeli ve her kaydın kullanıcı ve onun ürünlerinden biri hakkında bilgi içerdiği bir sonuç elde etmeliyiz.

Benzer bir sorgu, 2 SQL sorgusunun yerini alacaktır: malların bulunduğu tablodan ve kullanıcıların bulunduğu tablodan ayrı ayrı seçim yapmak. Ayrıca böyle bir talep kullanıcı ve ürünüyle anında eşleşecektir.

İsteğin kendisi çok basittir (bir öncekini anladıysanız):

SEÇİN * kullanıcılardan, ürünler NEREDE kullanicilar.id = ürünler.owner_id

Buradaki algoritma zaten basittir: ilk kayıt kullanıcılar tablosundan alınır. Daha sonra kimliği alınır ve ürünler tablosundaki tüm kayıtlar analiz edilir ve sonuca, sahip_kimliği kullanıcılar tablosundaki kimliğe eşit olan kayıtlar eklenir. Böylece ilk yinelemede ilk kullanıcının tüm malları toplanır. İkinci yinelemede ikinci kullanıcının tüm ürünleri toplanır ve bu şekilde devam eder.

Gördüğünüz gibi, çeşitli tablolardan seçim yapmak için kullanılan SQL sorguları en basiti değildir, ancak bunlardan elde edilen faydalar çok büyük olabilir; bu nedenle, bu tür sorguları bilmek ve kullanabilmek çok arzu edilen bir durumdur.

Bu kısa yazımızda MySQL başta olmak üzere veritabanları, örnekleme ve sayma konularından bahsedeceğiz. Veritabanlarıyla çalışırken, genellikle belirli bir koşul olsun ya da olmasın COUNT() satırlarının sayısını saymanız gerekir; bunu aşağıdaki sorguyla yapmak son derece kolaydır.

Kodu görüntüle MYSQL

Sorgu, tablodaki satır sayısını içeren bir değer döndürecektir.

Koşullu sayma

Kodu görüntüle MYSQL

Sorgu, tablodaki bu koşulu karşılayan satır sayısını içeren bir değer döndürecektir: var = 1

Farklı koşullara sahip birden fazla satır sayısı değeri elde etmek için birkaç sorguyu tek tek çalıştırabilirsiniz, örneğin

Kodu görüntüle MYSQL

Ancak bazı durumlarda bu yaklaşım ne pratik ne de optimaldir. Bu nedenle, tek bir sorguda aynı anda birden fazla sonuç elde etmek için bir sorguyu birden fazla alt sorguyla düzenlemek anlamlı hale gelir. Örneğin

Kodu görüntüle MYSQL

Böylece, veritabanında yalnızca bir sorgu çalıştırarak, çeşitli koşullar için satır sayısını içeren, örneğin birkaç sayım değeri içeren bir sonuç elde ederiz.

Kodu görüntüle METİN

c1|c2|c3 -------- 1 |5 |8

Birkaç ayrı sorguyla karşılaştırıldığında alt sorgu kullanmanın dezavantajı, yürütme hızı ve veritabanındaki yüktür.

Bir MySQL sorgusunda birden fazla COUNT içeren bir sorguya ilişkin aşağıdaki örnek biraz farklı şekilde oluşturulmuştur; SUM()'un yanı sıra IF(koşul, değer1, değer2) yapılarını da kullanır. Tek bir sorguda belirtilen kriterlere göre verileri seçmenize, ardından bunları özetlemenize ve sonuç olarak çeşitli değerleri görüntülemenize olanak tanır.

Kodu görüntüle MYSQL

Talepten de görülebileceği gibi oldukça kısa ve öz bir şekilde inşa edildi, ancak uygulama hızı da tatmin edici değildi, sonuç bu isteğin bir sonraki olacak,

Kodu görüntüle METİN

toplam|c1|c2|c3 -------------- 14 |1 |5 |8

Daha sonra, birden fazla COUNT() seçimi için üç sorgu seçeneğinin yürütme hızına ilişkin karşılaştırmalı istatistikler sunacağım. Sorgu yürütme hızını test etmek için, üç binden fazla kayıt içeren bir tabloyla her türden 1000 sorgu yürütüldü. Ayrıca, istek her seferinde sonuçların veritabanı tarafından önbelleğe alınmasını devre dışı bırakmak için SQL_NO_CACHE içeriyordu.

Yürütme hızı
Üç ayrı istek: 0,9 sn
Alt sorguları olan bir sorgu: 0,95 saniye
IF ve SUM yapısıyla bir istek: 1,5 saniye

Çözüm. Ve böylece veritabanına sorgular oluşturmak için çeşitli seçeneklerimiz var MySQL verileri birden fazla COUNT() ile, ayrı sorgulara sahip ilk seçenek pek kullanışlı değildir ancak en iyi hız sonucuna sahiptir. Alt sorgulara sahip ikinci seçenek biraz daha kullanışlıdır ancak yürütme hızı biraz daha düşüktür. Ve son olarak, sorgunun IF ve SUM yapılarını içeren üçüncü kısa ve öz versiyonu, en kullanışlı görünen versiyondur. düşük hız ilk iki seçeneğe göre neredeyse iki kat daha düşük performans. Bu nedenle, bir veritabanının çalışmasını optimize ederken, COUNT() ile alt sorgular içeren sorgunun ikinci sürümünü kullanmanızı öneririm, ilk olarak yürütme hızı en hızlı sonuca yakındır ve ikincisi, tek sorgu içinde böyle bir organizasyon oldukça uygundur .