MySQL bakım endeksleri


12

Parçalanmayı önlemek ve bazı sorguların yürütülmesini bir şekilde optimize etmek için MySQL'de dizinlerin nasıl korunacağı hakkında birçok araştırma yaptım.

Ben bir tablo VS kullanılabilir veri ve dizinler tarafından kullanılan alan arasındaki oranı hesaplayan bu formüle aşinayım.

Ancak ana sorularım hala cevapsız. Belki de bu, SQL Server'da dizin bakımına aşina olduğum gerçeğinden kaynaklanıyor ve MySQL'de bir şekilde benzer olması gerektiğini düşünüyorum.

SQL sunucusunda birkaç dizine sahip olabilirsiniz ve her birinin farklı bölümleme düzeyleri olabilir. Ardından bir tanesini alabilir ve geri kalanını etkilemeden belirli bir dizinde 'REORGANIZE' veya 'REBUILD' işlemini gerçekleştirebilirsiniz.

Bildiğim kadarıyla, böyle bir 'tablo parçalanması' yoktur ve SQL Server 'tablo parçalanması' düzeltmek için herhangi bir araç sağlamaz. Sağladığı şey, iç ve dış parçaların yanı sıra, dizin parçalanmasını (bir dizin VS tarafından kullanılan sayfanın sayısı ile o sayfanın dolgunluğu ve bitişiklik arasındaki oran gibi anlaşılır) kontrol etme araçlarıdır.

Bunların hepsini anlamak en azından benim için oldukça basittir.

Şimdi, MySQL'de dizinleri koruma sırası geldiğinde, sadece yukarıda belirtildiği gibi 'tablo parçalanması' kavramı vardır.

MySQL'de bir tablonun birkaç indeksi olabilir, ancak bu ünlü formülle 'fragmantasyon oranını' kontrol ettiğimde, her bir indeksin parçalanmasını görmüyorum, ama bir bütün olarak tablo.

MySQL dizinleri optimize etmek istediğinizde, (SQL Server gibi) üzerinde çalışmak için belirli bir dizin seçmiyorum. Bunun yerine, muhtemelen tüm dizinleri etkileyen tüm tabloda bir 'OPTIMIZE' işlemi gerçekleştiriyorum.

Tablo MySQL'de optimize edildiğinde, veri + endeksler VS tarafından kullanılan alan arasındaki oran genel alan azalır, bu da sabit sürücüde fiziksel alanın azalmasına dönüşen bir tür fiziksel yeniden organizasyon anlamına gelir. Bununla birlikte, dizin parçalanması sadece fiziksel alanla ilgili değildir, aynı zamanda ekleme ve güncellemeler nedeniyle zaman içinde değişen ağacın yapısıdır.

Sonunda InnoDB / MySQL'de bir tablo aldım. Bu tabloda 3 milyon kayıt, 105 sütun ve 55 dizin bulunmaktadır. 2,1 GB olan dizinler hariç 1,5 GB'dir.

Güncelleme, ekleme için bu tablo her gün binlerce kez vuruluyor (kayıtları gerçekten silmiyoruz).

Bu tablo yıllarca yaratıldı ve hiç kimsenin endeksleri korumadığından eminim.

Orada büyük bir parçalanma bulmayı bekliyordum, ama parçalanma hesaplamasını belirtilen şekilde yaptığımda

free_space / (data_length + index_length)

sadece% 0.2'lik bir parçalanmaya sahip olduğum ortaya çıktı. IMHO oldukça gerçekçi değil.

Yani büyük sorular:

  1. Tabloyu bir bütün olarak değil, MySQL'de belirli bir dizinin parçalanmasını nasıl kontrol ederim?
  2. OPTIMIZE TABLE aslında bir dizinin iç / dış parçalanmasını SQL Server'daki gibi düzeltir mi?
  3. MySQL'de bir tabloyu optimize ettiğimde, aslında tablodaki tüm dizinleri yeniden oluşturuyor mu?
  4. Bir endeksin fiziksel alanını azaltmanın (ağacın kendisini yeniden inşa etmeden) aslında daha iyi bir performansa dönüştüğünü düşünmek gerçekçi midir?

optimize tablo kesinlikle innodb kümelenmiş endeksi temizler

1
bu harika bir soru, sadece programlama değil. Ait olduğu yere taşınacak:>

Yanıtlar:


6

Endeks parçalanması çok abartılıyor. Onun hakkında endişelenme.

İki bitişik, biraz boş olan blok, doğal işlem olarak InnoDB tarafından birleştirilir.

Bir BTree'deki rastgele eylemler, doğal olarak ortalama% 69 dolu hale gelmesine neden olur. Tabii, bu% 100 değil, ama "sabitleme" yükü buna değmez.

SHOW TABLE STATUS size bazı metrikler verir, ancak kusurludur - "Data_free" belirli "boş" alanı içerir, ancak diğer "boş" alanı içermez.

Her blokta kullanılmayan alan vardır; ücretsiz 16KB bloklar; ücretsiz "uzantılar" (nMB parçaları); Biçilmeyi bekleyen MVCC satırları; yaprak olmayan düğümlerin kendi parçalanmaları vardır; vb.

Percona ve Oracle, bir endeksin ne kadar büyük olduğuna (blok sayısı) bakmak için farklı yollara sahiptir. "Ücretsiz" ifadesinin sınırlı tanımı nedeniyle hiçbirini kullanışlı bulmuyorum. Görünüşe göre bloklar (her biri 16KB) parçalar halinde (birkaç MB) tahsis edilir, böylece her türlü parçalanma olduğuna inanmaya yol açar. Gerçekte, genellikle bu çoklu MB yığınlarından sadece birkaçıdır. Ve OPTIMIZE TABLEalanın hiçbirini telafi etmek zorunda değildir.

SQL Server BTrees kullanıyorsa, "parçalanma" olmadığını söylemek yalan söylüyor. Bir "blok bölünmesi" ne olduğunu düşünün. Veya sürekli birleştirme yükünü düşünün. Her iki şekilde de kaybedersiniz.

Ayrıca, bir tablonun ve bir endeksin esasen özdeş yapılar olduğunu unutmayın:

  • B + Ağacı, bazı dizinlere göre
  • "Veri" PRIMARY KEY dayanmaktadır; her ikincil dizin, dizinini temel alan bir B + Ağacıdır.
  • "Veri" nin yaprak düğümü, tablonun tüm sütunlarını içerir.
  • İkincil bir dizinin yaprak düğümü, o ikincil dizinin sütunlarını ve PRIMARY KEY sütunlarını içerir.

Varsa innodb_file_per_table = ON, OPTIMIZE TABLE sonrasında .ibddosyanın boyutuna bakarak (varsa) büzülmeyi açıkça görebilirsiniz . Çünkü OFF, bilgi gömülüdür ibdata1, ancak SHOW TABLE STATUStüm "boş" alanlar her tabloya ait olduğu için oldukça doğru olabilir. Önceden tahsis edilmiş parçalar hariç.

Yeni optimize edilmiş bir tablo başına dosya tablosunun tam olarak 4M, 5M, 6M veya 7M Data_free'ye sahip olduğunu fark edebilirsiniz. Yine, bu ön tahsis ve size dakika detaylarını vermeme.

On yıldan fazla bir süredir InnoDB ile çalıştım; Büyük ve küçük binlerce farklı masa ile çalıştım. Ben binde sadece bir masaya gerçekten ihtiyacım var diyorum OPTIMIZE TABLE. Diğer masalarda kullanmak israftır.

105 sütun çok, ama belki de çok fazla değil.

Bir tabloda 55 dizin var mı? Bu kötü. Bu, başına 55 güncellemedir INSERT. Bunu daha ayrıntılı tartışalım. Aklınızda bulundurun, INDEX(a)eğer varsa da işe yaramaz INDEX(a,b). Ve INDEX(flag)düşük kardinalite nedeniyle işe yaramaz. (Ancak INDEX(flag, foo)faydalı olabilir.)

S1: Verilerdeki veya ikincil dizinlerdeki tüm parçalanma biçimlerini kontrol etmenin iyi bir yolu yoktur.

Q2, Q3: OPTIMIZE TABLEtabloyu CREATEingyeni bir tablo ve INSERTingtüm satırlarla yeniden oluşturur, sonra RENAMEingve DROPping. Verilerin PK düzeninde yeniden eklenmesi, verilerin iyi birleştirilmesini sağlar. Dizinler başka bir konudur.

S4: Sen olabilir DROP ve reCREATEher indeks bunu temizlemek için. Ancak bu son derece yavaş bir süreçtir. 5.6'nın bazı hızları var, ancak birleştirme konusunda yardımcı olup olmadıklarını bilmiyorum.

O ALTER TABLE ... DISABLE KEYSzaman ENABLEonlar da mümkündür . Bu mayıs daha verimli bir defada tüm ikincil indeksler yeniden.


Rick, dosya değil, '105' alan demek istedim
Nicolas

1

Tabloyu bir bütün olarak değil, MySQL'de belirli bir dizinin parçalanmasını nasıl kontrol ederim?

Geçmek.

OPTIMIZE TABLE aslında bir dizinin iç / dış parçalanmasını SQL Server'daki gibi düzeltir mi?

Tabloyu ve dizinlerini tamamen yeniden oluşturur.

MySQL'de bir tabloyu optimize ettiğimde, aslında tablodaki tüm dizinleri yeniden oluşturuyor mu?

Aynı soru ile aynı soru.

Bir endeksin fiziksel alanını azaltmanın (ağacın kendisini yeniden inşa etmeden) aslında daha iyi bir performansa dönüştüğünü düşünmek gerçekçi midir?

Ağacı yeniden inşa etmeden alanı azaltabileceğinizi düşünmek gerçekçi değil . Birlikte gidiyorlar.


Cevap 1: Her ne kadar çok doğru olmasa da, sütunda SHOW TABLE STATUS LIKE 'mytable'bir ipucu verecektir data free. dev.mysql.com/doc/refman/5.6/tr/show-table-status.html
Jehad Keriaki

Biliyorum, ama bu hala belirli bir endeksin alanını eksik
Nicolas
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.