InnoDB motoru ile kesici uç gecikmesi nasıl kullanılır ve kesici uç ifadeleri için daha az bağlantı nasıl kullanılır?


10

Ben veritabanı yazma, yaklaşık ~ 70% ekler ve% 30 okur bir sürü içeren bir uygulama üzerinde çalışıyorum. Bu oran aynı zamanda bir okuma ve bir yazma olduğunu düşündüğüm güncellemeleri de içerir. Insert deyimleri sayesinde, birden fazla istemci aşağıdaki insert deyimi aracılığıyla veri tabanına veri ekler:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

Soru, insert_delay kullanmalı mysq veya mysqli_multi_query mekanizmasını kullanmalıyım çünkü insert deyimi sunucuda ~% 100 cpu kullanıyor. Ben gecikmeli eklemek mümkün değil bu yüzden benim veritabanında InnoDB motoru kullanıyorum. Sunucuda ekleme ~ 36k / saat ve% 99.89 okunur, ayrıca tek bir sorguda yedi kez veri almak için select deyimi kullanıyorum , bu sorgu yürütmek için sunucuda 150 saniye sürer. Bu görev için ne tür bir teknik veya mekanizma kullanabilirim? Sunucu belleğim 2 gb, belleği genişletmeli miyim? Bu soruna bir göz atın, herhangi bir öneri bana minnettar olacaktır.

Tablonun yapısı:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

Benim veritabanı mevcut durumu, benim veritabanı için çok yavaş 41k eklemeler (yazar) gösterir.

veritabanı durumu


Tablonun tanımını verebilir misiniz? (tüm sütunlar, veri türleri ve dizinler)
ypercubeᵀᴹ

SHOW FULL PROCESSLIST% 100 işlemci alırken kısa bir açıklama yapabilir misiniz ? Kaç bağlantıya izin veriyorsunuz veya bu süre zarfında kaç bağlantı yapılıyor?
Derek Downey

Lütfen şu iki sorguyu çalıştırın: SHOW GLOBAL VARIABLES LIKE 'innodb%';ve SELECT VERSION();çıktılarını görüntüleyin.
RolandoMySQLDBA

Lütfen yürütmekte olduğunuz saniye başına kesici uç sayısını sağlayın.
dabest1

Kodunuz SQL enjeksiyonuna çok duyarlıdır. Hazırlanan ifadeleri ve parametreli değerleri kullanın.
Aaron Brown

Yanıtlar:


12

Okuduğunuzdan sonra daha fazla yazdığınızdan, aşağıdakileri tavsiye etmek istiyorum

InnoDB'nin iyi ayarlanması anahtar olacaktır

Tampon Havuzu ( innodb_buffer_pool_size tarafından boyutlandırılmıştır )

Yana InnoDB'nin desteklemediği INSERT GECİKMİŞ büyük InnoDB'nin Tampon Havuz sen INSERT alabilirsiniz yakın şey GECİKMİŞ kullanılarak,. Tüm DML'ler (INSERT'ler, UPDATE'ler ve DELETE'ler) InnoDB Arabellek Havuzunda önbelleğe alınır. Yazmalarla ilgili işlem bilgileri hemen Yinele Günlüklerine (ib_logfile0, ib_logfile1) yazılır. Buffer Pool'da yayınlanan yazılar ibdata1 (İkincil İndeksler için InsertBuffer, Çift Yazma Tamponu) aracılığıyla periyodik olarak bellekten diske temizlenir. Tampon Havuzu ne kadar büyük olursa, INSERT miktarı o kadar fazla önbelleğe alınabilir. 8 GB veya daha fazla RAM'e sahip bir sistemde, innodb_buffer_pool_size olarak RAM'in% 75-80'ini kullanın. Çok az RAM bulunan bir sistemde,% 25 (işletim sistemini barındırmak için).

CAVEAT: Yazmaları daha da hızlandırmak için innodb_doublewrite değerini 0 olarak ayarlayabilirsiniz , ancak veri bütünlüğü riski altındadır. Ayrıca InnoDB'yi işletim sistemine önbelleğe almayı önlemek için innodb_flush_method öğesini O_DIRECT olarak ayarlayarak işleri hızlandırabilirsiniz .

Günlükleri Yeniden Yap ( innodb_log_file_size tarafından boyutlandırılmıştır )

Varsayılan olarak, yineleme günlükleri ib_logfile0 ve ib_logfile1 olarak adlandırılır ve her biri 5 MB olur. Boyut, innodb_buffer_pool_size öğesinin% 25'i olmalıdır. Yinele günlükleri zaten varsa, yeni ayarı my.cnf dosyasına ekleyin, mysql'yi kapatın, silin ve mysql'yi yeniden başlatın .

Günlük Arabelleği ( innodb_log_buffer_size tarafından boyutlandırılmıştır )

Günlük arabelleği, yineleme günlüklerine girmeden önce RAM'deki değişiklikleri tutar. Varsayılan 8M'dir. Günlük arabelleği ne kadar büyük olursa, Disk G / Ç'si o kadar az olur. KOMİTELER'i milisaniye kadar yavaşlatabileceğinden çok büyük işlemlere dikkat edin.

Birden Fazla CPU'ya Erişim

MySQL 5.5 ve MySQL 5.1 InnoDB Eklentisi, InnoDB Depolama Motorunun birden fazla CPU'ya erişmesini sağlayacak ayarlara sahiptir. Ayarlamanız gereken seçenekler şunlardır:

  • innodb_thread_concurrency , InnoDB'nin açık tutabileceği eşzamanlı iş parçacığı sayısının üst sınırını ayarlar. Genellikle bunun için ayarlanması önerilir (2 X CPU Sayısı) + Disk Sayısı. Geçen yıl, InnoDB Depolama Motorunu çalıştığı ortam için en iyi iş parçacığı sayısını bulmak üzere uyarmak için bunu 0'a ayarlamanız gerektiğini ilk elden Percona NYC Konferansı'ndan öğrendim.
  • innodb_concurrency_tickets eşzamanlılık kontrolünü cezasızlıkla atlayabilecek iş parçacığı sayısını ayarlar. Bu sınıra ulaşıldıktan sonra, iş parçacığı eşzamanlılık denetimi yeniden norm haline gelir.
  • innodb_commit_concurrency , gerçekleştirilebilecek eşzamanlı işlemlerin sayısını belirler. Varsayılan değer 0 olduğu için, bunun ayarlanmaması herhangi bir sayıda işlemin aynı anda yapılmasına izin verir.
  • innodb_thread_sleep_delay , InnoDB sırasına yeniden girmeden önce bir InnoDB iş parçacığının hareketsiz kalabileceği milisaniye sayısını ayarlar. Varsayılan 10000 (10 sn) 'dir.
  • innodb_read_io_threads (bunu 3000 olarak ayarlayın) ve innodb_write_io_threads (bunu 7000 olarak ayarlayın) (her ikisi de MySQL 5.1.38'den beri) okuma ve yazma için belirtilen sayıda iş parçacığı ayırır. Varsayılan değer 4 ve maksimum değer 64'tür. Bunları 64 olarak ayarlayın. Ayrıca, innodb_io_capacity değerini 10000 olarak ayarlayın.

MySQL 5.5'e yükseltin

MySQL 5.0 sürümüne sahipseniz, MySQL 5.5 sürümüne yükseltin. MySQL 5.1.37 veya önceki sürümüne sahipseniz, MySQL 5.5 sürümüne yükseltin. MySQL 5.1.38 veya üst sürümüne sahipseniz ve MySQL 5.1'de kalmak istiyorsanız, InnoDB Eklentisini yükleyin. Bu şekilde, InnoDB için tüm CPU'lardan yararlanabilirsiniz.


benim sunucu belleği 2GB, bu yüzden belleğe göre ben innodb tampon havuzu 500M ve günlük dosyaları% 25 havuz, ayrıca günlük tampon 64M olarak ayarlayın. Ama yine de sunucu yoğun. Belleği yükseltmeli miyim? Ayrıca sunucum 32 bit ubuntu'da, bu yüzden max i belleği 4 GB'a ayarlayabilir.
Shashank

Sunucu sadece MySQL (apache yok, PHP yok) içinse, innodb_buffer_pool_size 2GB'ın% 75'ini oluşturabilir, bu da 1536M'dir. 4 GB'ye yükseltirseniz, innodb_buffer_pool_size 3G olabilir. Günlük dosyaları belirttiğiniz gibi arabellek havuzunun% 25'i olmalıdır.
RolandoMySQLDBA

Sunucu apache2, mysql ve php çalıştırıyor, bu durumda bellek yükseltme için gitmek gerekir mi yoksa innodb arabellek havuzu dışında herhangi bir optimum çözüm var mı?
Shashank

Bu adam sizinle aynı fikirde değil: percona.com/blog/2008/11/21/… Percona ile tartışmak zor.
Zenexer

Rolando - 5.6 ve 5.7 güncellemeleriyle cevaba eklemenizi öneririz. Varsayılanlar değişti; diğer ayarlar da mevcuttur; Belki Percona ve MariaDB ve 8.0 ipuçlarını içerir.
Rick James

2

INT (2) hala 4 bayt kullanıyor - belki de TINYINT UNSIGNED mi demek istediniz?

Setno'da kaç farklı değer var? Küçükse, KEY (setno) asla kullanılmaz. INSERTing bu dizini güncellemelidir; KEY kaldırıldığında INSERT biraz hızlanır.

CHAR (10) - Her flagzaman 10 karakter uzunluğunda mı? Ve utf8'de? Belki de VARCHAR (10) CHARACTER SET ascii bayrağını kullanabilirsiniz.

Eklerinizi toplu halde - bir seferde 100 kez 10 kat daha hızlı çalışacaktır. (100'den fazlası 'azalan getirilere' giriyor.)

Otomatik taahhüdün değeri nedir? Her bir INSERT'i BEGIN ... COMMIT'e mi sarıyorsunuz? İnnodb_flush_log_at_trx_commit değeri nedir?


veri farklı değerlerle farklı müşteriler gibi dış kaynak yoluyla insert ise ben toplu insert nasıl elde edersiniz .... bu i kullanılırsa güvenilirdir: code(col1, col2, col3) değerleri (val1, val2, VAL3) insert t_name içine, (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3); code
Shashank

1

Bir kuyruk oluşturun. Uygulama bir seferde bir sıra 1 satırına yazacak ve daha sonra satırları çıkaracak ve son eklemeden bu yana geçen zamanın satır sayısına göre toplu olarak bir veritabanına ekleyecektir.

Bir seferde 10.000 kesici ucun en hızlı nerede olduğunu gördüm, bu yüzden tatlı bir yer bulmak için test etmeniz gerekir.

Kendi basit kuyruk sisteminizi oluşturabilir veya mevcut bir sistemi kullanabilirsiniz. Bazı örnekler: HornetQ ve File :: Queue . İşte SE bazı diğer iyi seçenekleri listeleyen bir yazı: Mesaj kuyrukları perl, php, python .


Bu yaklaşımı kabul ediyorum - bir uygulamada 5 saniyede bir ~ 1500 insert topluyorum ve alt saniye. mysql, toplu eklerin gerçekten çok hızlı olmasını sağlayan dahili olarak uygulanan bir mekanizmaya sahip gibi görünüyor.
Don Wool
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.