I'm using siege to test the speed of a new site and I've found it could only handle around 30 concurrent connections per second using an AWS RDS small instance - small database. (I tried larger database and got more connections but it was still strangely low).
I've done a lot of testing to find the weak link and (eg: tested nginx/php-fpm with std HTML page, with php included, with memcached sessions) and this all works fine... its the database that is the issue.
I have 2 queries below - the first is just a test and it works fine/fast - I can get 3500 hits if run 100 concurrent connections over 20 seconds:
$database_users = new database('dbname');
$sql='SELECT COUNT(userid) as yes FROM login;';
$pds=$database_users->pdo->prepare($sql); $pds->execute(array()); $row=$pds->fetch();
echo $row['yes'];
The query below however is slow and I only get around 70 hits - its the query I use:
$database_users = new database('dbname');
$sql='SELECT a.countryCode FROM geoCountry AS a LEFT JOIN geoIPv4 AS b ON a.pid=b.geoCountry_pid WHERE \'2091528364\' BETWEEN startipNum AND endipNum;';
$pds=$database_users->pdo->prepare($sql); $pds->execute(array()); $row=$pds->fetch();
echo $row['countryCode'];
First query runs in 0.1 seconds and second runs in 0.3 seconds when I use a remote query tool.
I'm trying to understand why I would get such bad performance with the second. Wouldn't php/database just wait for the query to complete and then respond. Its only 0.2 of a second.
I can send other details if needed like php-fpm config.
any advice would be greatly appreciated - thankyou
CREATE TABLE `geoCountry` (
`pid` tinyint(3) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`countryCode` char(2) NOT NULL COMMENT 'Country Code',
`zipEnabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1=Has Zip Codes, 0=No Zip Codes',
`english` varchar(75) NOT NULL COMMENT 'Language',
`indonesian` varchar(75) NOT NULL COMMENT 'Language',
`japanese` varchar(75) NOT NULL COMMENT 'Language',
PRIMARY KEY (`pid`),
UNIQUE KEY `countryCode` (`countryCode`),
KEY `zipEnabled` (`zipEnabled`),
CONSTRAINT `geoCountry_zipEnabled` FOREIGN KEY (`zipEnabled`) REFERENCES `xfk_generic_binary` (`binary`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=249 DEFAULT CHARSET=utf8 COMMENT='Country Codes linked to Country Names'
CREATE TABLE `geoIPv4` (
`pid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`geoCountry_pid` tinyint(3) unsigned NOT NULL COMMENT 'geoCountry Pid',
`startipNum` int(10) unsigned NOT NULL COMMENT 'Start IP Address',
`endipNum` int(10) unsigned NOT NULL COMMENT 'End IP Address',
PRIMARY KEY (`pid`),
KEY `geoCountry_pid` (`geoCountry_pid`),
CONSTRAINT `geoIPv4_geoCountry_pid` FOREIGN KEY (`geoCountry_pid`) REFERENCES `geoCountry` (`pid`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=148890 DEFAULT CHARSET=utf8 COMMENT='IPv4 Ranges linked to Country Codes';
* is it possible its php-fpm not waiting for the reply to come back or something to do with how siege works? Note: seige seems to work fine if the number of concurrent connections is low.
geoIPv4.geoCountry_pidis indexed. Also, since you're not actually binding any variables, don't usePDO::prepare()- usePDO::query()instead - it'll save you a call to the database on every query.SHOW CREATE TABLE <table_name>statements along withSHOW INDEXES FROM <table_name>.