Ruby ile KyotoCabinet – 3

Merhabalar,

Bir Önceki yazımızda Ruby üzerinden KyotoCabinet’e 1.000.000 (1 milyon) veri girişini çok kısa bir sürede tamamlamıştık. Daha sonra içime bir kurt düştü, acaba mysql’de durum nasıldı? Yani aynı koşullar altında mysql veri tabanına 1.000.000 kayıdı kaç sn içerisinde yazabilecektim?

Makinanın Özelliklerini bir Önceki yazımızda vermiştim.

Bu işlemin testi için Öncelikle kendimize oldukça hızlı olduğuna inandığım, KyotoCabinet’in Ruby arabiriminde olduğu gibi C dili ile yazılmış MySQL/Ruby bir arabirim kütüphanesi buldum ve 2.8.2 versiyonunu kurdum. Bununla beraber MySQLClient versiyonunun 5.1.41 olduğunu sÖylemeliyim.

Daha sonra key, value tutacağımız bir veri tabanı oluşturdum. Öncelikle MyISAM motorunu kullanan bir tablo oluşturdum ve testlerimi bu tablo üzerinde yaptım.

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` CHAR(12) UNICODE NOT NULL,
  `value` CHAR(12) UNICODE NOT NULL,
  PRIMARY KEY (`key`)
)
ENGINE = MyISAM
CHARACTER SET utf8 COLLATE utf8_turkish_ci;

Bu tablo için aşağıdaki kod parçasını uyguladım;

require "mysql"

begin
  dbh = Mysql.real_connect("localhost", "kyoto_cabinet", "kyoto_cabinet", "kyoto_cabinet")
  dbh.autocommit(false)
  st = dbh.prepare("insert into simple_table values (?,?)")
 
  start_number = 905420000001
  start_time = Time.now
  puts "sira;gecen_sure;toplam_gecen_sure"
  100.times { |index|
    first_loop_start_time = Time.now
    10000.times {
      start_number += 1
      st.execute(start_number, start_number)
    }
    dbh.commit
    loop_elapsed = Time.now.to_f - first_loop_start_time.to_f
    total_elapsed = Time.now.to_f - start_time.to_f
    puts index.to_s + ";" + loop_elapsed.to_s + ";" + total_elapsed.to_s
  }
  puts "1.000.000 kayit eklenmistir. Toplam süre: " + (Time.now.to_f - start_time.to_f).to_s  
rescue Mysql::Error => e
  puts "Error code: #{e.errno}"
  puts "Error message: #{e.error}"
  puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
ensure
  # disconnect from server
  dbh.close if dbh
end

* Hemen belirtmekte fayda var, bu kod parçasının boşta (insert olmadan) çalışması sırasında her 10.000 kayıt için ortalama ~0.014 sn ve toplamda ~1.43 sn harcanmıştır.

Sonuç pek de beklediğimiz gibi değil; ortalama her 10000’lik kayıdı ~1.19 sn’de işleyebildik. Toplamda ~119 sn harcamış olduk. Bu işte bir terslik var sanki, her ne kadar MySql sisteminin hızlı olması için CHAR veri tipini kullansam da Ruby’de kullandığım veri tipi numeric, bu nedenle Mysql üzerindeki tablo tasarımını aşağıda gÖsterildiği şekilde değiştirdim.

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` BIGINT ,
  `value` BIGINT ,
  PRIMARY KEY (`key`)
)
ENGINE = MyISAM;

Ve tekrar çalıştırdım. Sonuç; ortalama olarak her 10000’lik kayıdı ~0.78 sn’de işleyebildik. Toplamda ~78 sn harcamış olduk. Bu şekilde %35’lik iyileşme kaydetmiş olduk fakat bu rakamlar kyotoCabinet rakamlarına gÖre oldukça yüksek (yaklaşık 10 kat kadar).

Fakat bu sonuçta benim için yetmedi. MySql’in daha iyileştirilebileceğini düşünüyorum. Bu nedenle aşağıdaki gibi bir tablo oluşturdum;

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `value` BIGINT UNSIGNED,
  PRIMARY KEY (`key`)
)
ENGINE = MyISAM;

Testi tekrar çalıştırdım, sonuçta bir Önceki AUTO_INCREMENT’siz haline gÖre pek bir değişim olmadı ama hazır testi yapmışım, sonuçların arasından çıkarmak istemedim :)

Daha sonra MyISAM yerine InnoDB kullanmayı denedim;

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` BIGINT ,
  `value` BIGINT ,
  PRIMARY KEY (`key`)
)
ENGINE = InnoDB;

Sonuç; ortalama olarak her 10000’lik kayıdı ~0.81 sn’de işleyebildik. Toplamda ~80.1 sn harcamış olduk. Diğerlerinden çok farklı değil.

Ve son olarak InnoDB veya MyISAM yerine MEMORY motorunu kullandım.

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` BIGINT ,
  `value` BIGINT ,
  PRIMARY KEY (`key`)
)
ENGINE = MEMORY;

Sonuç; ortalama olarak her 10000’lik kayıdı 0.57 sn’de işleyebildik. Fakat test yarıda kaldı. 600.000 kayıttan sonra “table is full” hatası aldık. Bu hatayı alana kadar 35 sn. geçmişti.

Ve son olarak, her 10000 kayit kümesi için ortalama oluşan sonuçlar aşağıdadır;

KyotoCabinet için;
Boşta: 0.0140892158855091
Toplam: 0.0746499228477478
Gerçek: 0.0605607069622387

MySql Char için;
Boşta: 0.0142888712882996
Toplam: 1.18662132501602
Gerçek: 1.17233245372772

MySql BIGINT
Boşta: 0.01428887128830
Toplam: 0.77685088634491
Gerçek: 0.76256201505661

MySql AUTO-INC
Boşta: 0.014288871288300
Toplam: 0.791638641357422
Gerçek: 0.777349770069122

MySql InnoDB and BIGINT
Boşta: 0.014288871288300
Toplam: 0.809741024971008
Gerçek: 0.795452153682709

Kolay gelsin.

Share