I use python (Django) for my web-shop.
When I tested high loading (db access) got interesting results:
python 10 process = 200sec / 100% CPU utilisation
perl 10 process = 65sec / 35% CPU utilisation
Centos 6, python 2.6, mysql 5.5, standard libraries, mysql-server on other server. Table product_cars have 70 000 000 records.
Why python-program so slow?
Python program:
#!/usr/bin/python
import MySQLdb
import re
from MySQLdb import cursors
import shutil
import datetime
import random
db0 = MySQLdb.connect(user="X", passwd="X", db="parts")
cursor0 = db0.cursor()
cursor0.execute('SET NAMES utf8')
now = datetime.datetime.now()
for x in xrange(1, 100000):
id = random.randint(10, 50000)
cursor0.execute("SELECT * FROM product_cars WHERE car_id=%s LIMIT 500", [id])
cursor0.fetchone()
Perl program:
#!/usr/bin/perl
use DBI;
my $INSTANCE=$ARGV[0];
my $user = "x";
my $pw = "x";
my $db = DBI->connect( "dbi:mysql:parts", "x", "x");
my $sql= "SELECT * FROM product_cars WHERE car_id=? LIMIT 500";
foreach $_ ( 1 .. 100000 )
{
$random = int(rand(50000));
$cursor = $db->prepare($sql);
$cursor->execute($random) || die $cursor->errstr;
@Data= $cursor->fetchrow_array();
}
$cursor->finish;
$db->disconnect;
update1
Interesting thing:
select always row with id=1:
Сlear that MYSQL use cache and query will be very fast, but again slow and 100% CPU utilisation. But same perl or ruby code work quick.
if replace string in python code:
# remove "SET NAMES utf8" string - this has no impact
# python-mysql use "%s", but not "?" as parameter marker
id = 1
for x in xrange(1, 100000):
id = 1
cursor0.execute("SELECT * FROM product_cars WHERE car_id=%s LIMIT 500", [id])
cursor0.fetchone()
Same code in perl:
foreach $_ ( 1 .. 20000 )
{
$cursor = $db->prepare( "SELECT * FROM product_cars WHERE car_id=? LIMIT 500";);
$cursor->execute(1);
# while (my @Data= $cursor->fetchrow_array())
if ($_ % 1000 == 0) { print "$_\n" };.
@Data= $cursor->fetchrow_array();
# print "$_\n";
}
Code in ruby:
pk=2
20000.times do |i|
if i % 1000 == 0
print i, "\n"
end
res = my.query("SELECT * FROM product_cars WHERE car_id='#{pk}' LIMIT 500")
res.fetch_row
end
update 2
Exec SQL "SELECT * FROM product WHERE id=1" (string without params) 100000 times
Python: ~15 sec 100% CPU 100%
Perl: ~9 sec CPU 70-90%
Ruby: ~6 sec CPU 60-80%
MySQL-server on other machine.
update 3
Tried use oursql and pymysql - worse results.
%sas the parameter marker, and supplying the actual args as a list instead of a tuple is unconventional rather than incorrect.$cursor = $db->prepare($sql);to outside the loop.fetchrow_arrayref) which costs a bit more. Finally, leaving theprepareinside the loop keeps Perl from taking advantage of prepared statements.