InnoDB tablosundan alan silme ve geri kazanma


14

(Sadece okuma) için daha fazla veri yazmıyorum 700GB InnoDB tablo var. Daha eski verileri silmek ve (boş kaldığım gibi) bu disk alanı geri almak istiyorum. Silme kısmı oldukça kolaydır, çünkü bir auto-inc birincil dizinim var, bu yüzden onu kullanarak parçalar halinde yineleyebilir ve satırları silebilirim, ancak bu bana alanı geri getirmeyecek. OPTIMIZE TABLEIrade varsayalım ama bu sonsuza kadar 700GB bir tablo alabilir, bu yüzden göz ardı başka bir seçenek var mı?

RolandoMySQLDBA tarafından düzenleyin

Tablonuzun olduğu varsayılırsa mydb.mytable, lütfen aşağıdaki sorguyu çalıştırın ve tablonun büzülmesi için gereken disk alanını belirleyebilmeniz için buraya gönderin:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

İzin verilirse, tablo yapısını da görmemiz gerekir.

Noam tarafından düzenle

Sorgunun çıktısı budur:

datsize ndxsize tblsize
682.51 47.57 730.08

Bu tablo yapısı ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

Yalnızca verileri yakalamak için başka bir disk biriminiz var mı ???
RolandoMySQLDBA

@RolandoMySQLDBA Bağlayabileceğim harici bir sabit diskim var. Bu sayılır mı?
Noam

@RolandoMySQLDBA ama tabii ki başka bir 700GB'ye gerek kalmadan bir alanı silmek için bir seçenek gibi olurdu
Noam

@RolandoMySQLDBA ekstra disk boyutu herhangi bir performans sorununa neden oluyor mu?
Aris

@ Diske ve arama süresine bağlı olarak olabilir. Bu günlerde, çoğu disk şimdi daha iyi performans gösteriyor, ancak tablonuzda büyük seyrek disk boşluklarına sahipseniz, döngüleri (gerçekten hızlı gidiyor) israf etmektir. Bu özellikle normalde 16K bloklarda sabitlenen InnoDB için geçerlidir. 16K blokların iç parçalanmasıyla, tabloyu kullanarak birleştirmek isteyebilirsiniz ALTER TABLE ... ENGINE=InnoDB;(eğer bunu yapmak için odanız varsa). Çoğu çok hızlı SSD'lerinden memnunlar ve artık endişelenmiyorlar.
RolandoMySQLDBA

Yanıtlar:


21

Bu iyi bir soru. Birkaç çözümünüz var ama masanız oldukça büyük, bu yüzden hiçbiri acı çekmeyecek :)

InnoDB tablolarını "küçültmek" için üç çözümünüz vardır:

1. OPTİMİZE TABLOSU

OPTIMIZE TABLEBahsettiğiniz gibi kullanabilirsiniz , ancak innodb_file_per_tabledeğişkeni önemsemelisiniz :

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Açıklamama izin ver:

OPTIMIZE TABLEInnoDB tablolar, tablo kilitler çok odalı, (sonuç daraltılır yüzden), orijinal tabloyu bırakıp orijinal adıyla yeni bir tablo adlandırmak yeni bir temiz tablodaki verileri kopyalayın. Bu nedenle tablonuzun iki katının diskinizde mevcut olmasına dikkat etmelisiniz (Çalışma sırasında 2x700GB gerekir).

İnnodb_file_per_table = ON konumunda olduğunuzda. Tüm tablolar uygun veri dosyasına sahiptir. Bu nedenle, işlem tamamlandığında OPTIMIZEifade yeni bir veri dosyası (~ 700GB) oluşturacak, MySQL orijinal olanı bırakacak ve yenisini yeniden adlandıracaktır (böylece sonunda 700GB - muhtemelen daha az daraltılacağı için - daha az veri) operasyon sırasında oluşturulan serbest bırakılacaktır)

İnnodb_file_per_table = OFF içindeyken. Tüm veriler bir veri dosyasına gider: ibdata . Bu dosyanın üzücü bir özelliği var, küçülemiyor. Yani sırasında OPTIMIZEsüreç, yeni tablo (700GB yakın) oluşturulacak, ama daha damla ve yeniden adlandırma işlemi (ve bitiminden sonra OPTIMIZEfazı) sizin ibdata ~ 700GB yayımlanan olmayacak, özgür bazı verileri istedi bu yüzden ancak 700GB var daha fazlası, değil mi?

2. ALTER TABLOSU

Ayrıca bir ALTER TABLEifade kullanabilirsiniz ALTER TABLE, aynı şekilde çalışacaktır OPTIMIZE TABLE. Sadece şunu kullanabilirsiniz:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLOSU (ONLINE)

Sorun OPTIMIZEve ALTER TABLEçalışma sırasında tabloyu kilitler. (Percona Toolkit dan: pt-online-şema değişikliği: Sen Percona aracını kullanabilirsiniz bağlantı ). pt-online-schema ... orijinal tablonun işlem sırasında okunmasına ve yazılmasına izin verdiğiniz tetikleyiciler ve geçici tablo ile bir mekanizma oluşturacaktır. Bu aracı üretimde ALTERoldukça büyük olan için kullanıyorum.

FOREIGN KEYTablonuza başvurmanız gerektiğini unutmayın , FK ve karışıklık yaratma riskini tetikler. Bu ön koşulları kontrol etmek için sorgulayın:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

İşte pt-online-schema-change nasıl kullanılır:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

İnnodb_file_per_table ile ilgili notumun bu çözüm için de geçerli olduğunu unutmayın.

4. mysqldump

Son çözüm, tüm veritabanlarını bir dökümünden yeniden oluşturmaktır. Çok uzun ama çok verimli. Ibdata dosyasını "küçültmek" için tek çözüm olduğunu unutmayın.

Maks.


Ayrıca percona aracı çevrimiçi değiştirme tablosu seçeneğinde 700GB boş disk alanına ihtiyacım olacak mı?
Noam

Evet, pt-online, ALTER'i çevrimiçi yapmak için bazı mekanizmaları kullanır, ancak yine de bir ALTER yapar.
Maxime Fouilleul

@MaximeFouilleul ekstra disk boyutu herhangi bir performans sorununa neden oluyor mu?
Aris

1

Disk boyutunda kısa iseniz, pt-online-schema-change (ONLINE) ile önerilen Max gibi yapmanızı öneririm. Çok daha küçük bir masa (200GB) ile aynı durumda bulundum ve aynı anda biraz sıkıştırma yapmayı seçtim. Bunun çizgileri boyunca bir şey işe yaramalıdır:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Bu yalnızca barracuda dosya biçiminde ve tablonun COMPACT biçimindeyseniz çalışır. Ayrıca innodb_file_per_table etkin olmalıdır. Bu, özellikle çok fazla metin varsa ve 8K veya 4K gibi daha küçük KEY_BLOCK_SIZE kullanıyorsanız (varsayılan 16K'dır), tablonuzun boyutunda harikalar yaratabilir. Ayrıca, diğer bloglarda bu konuyla ilgili birden fazla ölçütten ne kadar alan kazanabileceğinizi kontrol edebilirsiniz, ancak MySQL belgeleri% 25 ila% 50 reklamı yapar (benim için neredeyse% 90'dı).

Bunun SELECT (MySQL belgelerinden) yaparken performansı da etkileyebileceğini unutmayın:

Bu nedenle, herhangi bir zamanda, tampon havuzu sayfanın hem sıkıştırılmış hem de sıkıştırılmamış formlarını ya da sadece sayfanın sıkıştırılmış formunu içerebilir ya da hiçbirini içermeyebilir.

MySQL ayrıca arabellek havuzunda değilken verileri sıkıştırmalıdır. Dikkatli olun.

Benim durumumda bu gerçekten iyi çalıştı. Uzun bir metnim vardı. 200GB 26GB oldu. Performanslar değiştirilmedi.

Daha ayrıntılı bilgi için şu bağlantıları kontrol edin:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

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.