Parçalanmış MySQL tablolarını bulma ve düzeltme


27

Bazı masaların parçalandığını belirten MySQLTuner'ı kullandım. kullandım

mysqlcheck --optimize -A

tüm tabloları optimize etmek için. Bazı tabloları düzeltti, ancak MySQLTuner hala 19 adet parçalı tablo buldu. hangi tabloların birleştirilmeye ihtiyacı olduğunu nasıl görebilirim? Belki OPTIMIZE TABLE, mysqlcheck'in çalışmadığı yerlerde çalışabilir mi? Veya başka ne denemeliyim?


1
Benim de benzer bir problemim var. MySQL 5.5 ve bazı InnoDB tabloları ile hiç bir zaman bozulmayacak yeni bir DB kuruyorum Data_free çekinin (KayakJim'in cevabında gösterilmiştir) InnoDB tablolarında yanlış olup olmadığını merak ediyorum.
saat

Yanıtlar:


38

Kısa cevap:

select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

"Bilmeniz gerekir" cevabı

ilk önce bir satır güncellendiğinde Mysql tablolarının parçalandığını anlamalısınız, bu yüzden bu normal bir durumdur. Bir tablo oluşturulduğunda, veri içeren bir döküm kullanarak içe aktarıldığını varsayalım, tüm satırlar birçok sabit boyutlu sayfada parçalanma olmadan depolanır. Değişken uzunluklu bir satırı güncellediğinizde, bu satırı içeren sayfa değişiklikleri saklamak için iki veya daha fazla sayfaya bölünür ve bu yeni iki (veya daha fazla) sayfa kullanılmayan alanı dolduran boş alanlar içerir.

Parçalanma çok fazla büyümezse, bu performansı etkilemez. Çok fazla parçalanma nedir, peki aradığınız sorguyu görelim:

  select  ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables  where  DATA_FREE > 0;

DATA_LENGTH ve INDEX_LENGTH, verilerinizin ve dizinlerinin kullandığı alan ve DATA_FREE, tüm tablo sayfalarında kullanılmayan toplam bayt miktarıdır (parçalanma).

İşte gerçek bir üretim tablosu örneği

| ENGINE | TABLE_NAME               | data_length | index_length | data_free |
| InnoDB | comments                 |         896 |          316 |         5 |

Bu durumda (896 + 316) = 1212 MB kullanarak bir Tablomuz var ve verilere 5 MB boş alan var. Bu, aşağıdakilerin "parçalanma oranı" anlamına gelir:

5/1212 = 0.0041

... Bu gerçekten düşük bir "parçalanma oranı" dır.

0.2'ye yakın (boş alanların% 20'si anlamına gelen) oranlara sahip tablolarla çalışıyorum ve sorgular üzerinde yavaşlama olduğunu fark etmedim, masayı optimize etsem bile, performans aynıdır. Ancak 800 MB'lık bir masaya optimize edilmiş bir masa uygulamak çok zaman alır ve masayı birkaç dakika boyunca bloke eder, bu da üretimde pratik değildir.

Bu yüzden, performansta ne kazandığınızı ve bir masayı optimize etmek için harcadığınız zamanı göz önünde bulundurursanız, OPTIMIZE DEĞİLSİNİZ.

Depolama için daha iyi olduğunu düşünüyorsanız, oranınızı görün ve optimize ederken ne kadar yer kazanabileceğinizi görün. Genellikle çok fazla değil, bu yüzden OPTIMIZE yapmamayı tercih ediyorum.

En iyileştirirseniz, bir sonraki güncelleme, bir sayfayı iki veya daha fazlasına bölerek boş alanlar oluşturur. Ancak, parçalanmış bir tabloyu parçalanmamış bir tablodan güncellemek daha hızlıdır, çünkü tablo parçalanmışsa bir satırdaki bir güncelleme mutlaka bir sayfayı bölmez.

Umarım bu sana yardımcı olur.


1
Bu birkaç yıl önce verilen bir cevap olmasına rağmen, data_free'nin ilgili tablo için değil tüm tablo alanı için bir stat olduğunu işaret edeceğimi düşündüm. Birden fazla tabloyu bir tablo alanında birlikte saklarsanız, data_free, tablonun birleştirilmesi gerektiğine inanmanız için sizi yanlış yönlendirebilir, bu yalnızca tablo alanında boş alanların olduğu anlamına gelir. En iyi duruma getirme tablosunun çalıştırılması ücretsiz uzantıları azaltmaz. Masanın birleştirilmesi serbest uzamayı bile artırabilir .
Bill Karwin

14

Sadece Felipe-Rojas'tan gelen cevaba eklemek için, fragman oranını sorgunun bir parçası olarak hesaplayabilirsiniz:

select ENGINE,
  concat(TABLE_SCHEMA, '.', TABLE_NAME) as table_name,
  round(DATA_LENGTH/1024/1024, 2) as data_length,
  round(INDEX_LENGTH/1024/1024, 2) as index_length,
  round(DATA_FREE/1024/1024, 2) as data_free,
  (data_free/(index_length+data_length)) as frag_ratio
FROM information_schema.tables
WHERE DATA_FREE > 0
ORDER BY frag_ratio DESC;

Bir masa küçük bir yüzdeye bölünmüşse (% 5'ten az?) O zaman muhtemelen tek başına bırakabilirsiniz.

Daha büyük olan herhangi bir şey varsa, db kullanımınıza, tabloları kilitlemeye vb. Bağlı olarak tabloyu birleştirmenin ne kadar önemli olduğunu değerlendirmeniz gerekecektir.


2

Optimize Tablosu gerçekten yaşadığınız sorunu çözecektir.

Yalnızca birkaç veritabanınız varsa, tüm veritabanlarınızı gözden geçirmek için PHPMyAdmin'i kullanabilirsiniz. Tepegözlü masaları ve ardından optimize etmek için seçin.

Çok fazla veritabanınız varsa, başka bir yöntem muhtemelen tercih edilir.

Her saat çalıştırmak için aşağıdaki PHP betiği kurulumunu cron olarak kullanıyorum.

$DB = new mysqli ('localhost', 'DbUser', 'DbPassword');
$results = $DB->query('show databases');
$allDbs = array();
while ($row = $results->fetch_array(MYSQLI_NUM))
{
    $allDbs[] = $row[0];
}
$results->close();
foreach ($allDbs as $dbName)
{
    if ($dbName != 'information_schema' && $dbName != 'mysql')
    {
        $DB->select_db($dbName);
        $results = $DB->query('SHOW TABLE STATUS WHERE Data_free > 0');
        if ($results->num_rows > 0)
        {
            while ($row = $results->fetch_assoc())
            {
                $DB->query('optimize table ' . $row['Name']);
            }
        }
        $results->close();
    }
}
$DB->close();

3
Eminim ki mysqlcheck --optimize -Abu aynı SQLOPTIMIZE TABLE <tablename>;
docwhat

2

Bu sayfaya rastladım ve Felipe-Rojas ve sysadmiral tarafından yapılan sorguları çok faydalı buldum. Ancak benim durumumda sorguyu WHM'nin phpMyAdmin'inde çalıştırıyordum ve sadece TABLE_NAME'ı almak veritabanı listelenmediği için yardımcı olmadı ve bazı veritabanları aynı tablo adlarına sahipti. Yani, basitçe eklemek TABLE_SCHEMA, bu sütunu da sağlayacaktır.

select  ENGINE, TABLE_SCHEMA, TABLE_NAME, Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free, (data_free/(index_length+data_length)) as frag_ratio from information_schema.tables  where  DATA_FREE > 0 order by frag_ratio desc

DB gösterir

ENGINE  | TABLE_SCHEMA  | TABLE_NAME    | data_length   | index_length  | data_free | frag_ratio

InnoDB  | db_name       | db_table      | 0             | 0             | 8         | 170.6667

"Düzeltmek" için phpMyAdmin'in çalıştırdığı yüksek "frag_ratio" ile sonuçlanan tabloların her biri için phpMyAdmin'deki Birleştirme tablosu bağlantısını kullandım:

ALTER TABLE `table_name` ENGINE = InnoDB;

0

MySQL'in InnoDB Motorunu kullanan bir tablonun temelde asla olması gerekmiyor OPTIMIZEd.

Her Data_freeikisinin de değeri sıfırdır ya information_schema.tablesda SHOW TABLE STATUSsıfırdır, hepsini yaptığınızı düşündüğünüzde bile tablonuzu / masalarınızı birleştirebilirsiniz. Ayrıca, bu metrik, gerçekleşebilecek ve gerçekleşebilecek birkaç parçalanmadan sadece biridir . (Ayrıca, bloklarda boşa harcanan, listeleri geri al, BTrees ve BTrees vs endeksleri vs.

Ve innodb_file_per_tablekullanımını zorlaştırıyor Data_free. Tablo ise ibdata1, o zaman Data_freebütün tablo belirtir; oldukça yararsız bir sayı. Tablo kendi .ibddosyasındaysa, hangisi daha büyükse, birkaç MB veya tablo boyutunun yüzde birkaç olması muhtemeldir.

Sildiğiniz Yalnızca çok satır ve tabloyu doldurmak niyetinde değilim, belki buna değer çalışır mümkün OPTIMIZE TABLE.

PARTITIONsAyrıca bir rahatsız edici miktarını gösterir Data_freeçünkü her bölüm genellikle "serbest" 4-7MB gösterir. Ve bu uzağa gitmeyecek.

Neden Birleştir?

  • İşletim sistemine geri dönmek için? Eh, sen olabilir sen olsaydı bu kısaca başarmak innodb_file_per_table=1. Ancak satır ekledikçe işletim sisteminden geri alırsınız.
  • Erişimi hızlandırmak için? Unut gitsin. Diskteki blokların düzeni nispeten rastgeledir ve son birkaç on yıldır. Yarım yüzyıl önce, blokları yeniden düzenlemek biraz önemliydi.
  • BTrees'i yeniden dengelemek için? Yani? Derhal tekrar dengesizleşecekler. Rasgele yerleştirilmiş BTrees için kararlı durum% 69'dur. Ve bu bile hesaba katılmaz Data_free.
  • MySQLTuner diyor ki? Bu ürünün ürpermesi gerekiyor.

Bir tarih notu. DBA'lara çoğunlukla MyISAM masalarında yardım ederken, ayda bir yardım edilen 1000 masadan 2'sini keşfettim OPTIMIZE. O zamandan beri, binlerce InnoDB masası ile çalıştım, henüz yardım edebileceği bir performans sorunu bulamadım OPTIMIZE. (Tabii ki, OPTIMIZEyardımcı olabilecek disk alanı sorunları oldu , ancak bu zorlaşıyor - genellikle DBA'nın çalışması için yeterli disk alanı yok OPTIMIZE!)

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.