'mysql slow on updates for a well optimized query

i am facing an issue with update state , which takes up to 4s on very small queries .

Count: 1  Time=3.87s (3s)  Lock=0.00s (0s)  Rows=0.0 (0), ***[***]@localhost
  UPDATE p_villages v SET v.resources='1 3273182 240000000 1500 245000 25,2 3273236 240000000 1500 245000 25,3 3273280 240000000 1500 245000 25,4 166973998 280000000 1500 3675000 325', v.cp='2941.8712 1867', v.crop_consumption=v.crop_consumption+1, v.troops_num='-1:11 0,12 0,13 0,14 9628,15 0,16 0,17 0,18 0,19 0,20 0,99 0', v.last_update_date=NOW() WHERE v.id='20899'



Count: 1  Time=2.97s (2s)  Lock=0.00s (0s)  Rows=0.0 (0), ***[***]@localhost
  UPDATE p_villages v
  SET
  v.update_key='38c47',
  v.resources='1 827064241 840000000 1500 800 0,2 814159650 840000000 1500 800 0,3 801255060 840000000 1500 800 0,4 839968830 840000000 1500 1200 0',
  v.cp='27.304202777778 1106',
  v.last_update_date=NOW()
  WHERE
  v.id='1084' AND v.player_id='22290'

example of query is :

db::query("UPDATE p_villages v SET v.resources=:res, v.cp=:cp, v.crop_consumption=v.crop_consumption+$troops_crop_consumption, v.troops_num=:tnum, v.last_update_date=NOW() WHERE v.id=:id", array(
            'res' => $this->_getResourcesString($resultArr['resources']),
            'cp' => $resultArr['cp']['cpValue'] . " " . $resultArr['cp']['cpRate'],
            'tnum' => $troopTrainingStr,
            'id' => intval($taskRow['village_id'])
        ));

id is indexed

updates : //

this is the result of explain

Your SQL query has been executed successfully.

explain UPDATE p_villages v
  SET
  v.update_key='38c47',
  v.resources='1 827064241 840000000 1500 800 0,2 814159650 840000000 1500 800 0,3 801255060 840000000 1500 800 0,4 839968830 840000000 1500 1200 0',
  v.cp='27.304202777778 1106',
  v.last_update_date=NOW()
  WHERE
  v.id='1084' AND v.player_id='1'



1   UPDATE  v   
    NULL
    range   PRIMARY,NewIndex2,NewIndex6 PRIMARY 4   const   1   100.00  Using where 

this is much more simple query , that takes 2.39s ..

Count: 5  Time=2.39s (11s)  Lock=0.00s (0s)  Rows=0.0 (0), ***[***]@localhost
  UPDATE g_settings gs SET gs.qlocked=1, qlocked_date=NOW() WHERE gs.qlocked=0

as requested this is the result of query SHOW CREATE TABLE p_villages

p_villages  CREATE TABLE `p_villages` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `rel_x` smallint(6) DEFAULT NULL,
  `rel_y` smallint(7) DEFAULT NULL,
  `field_maps_id` tinyint(4) DEFAULT NULL,
  `rand_num` int(11) DEFAULT NULL,
  `image_num` tinyint(4) DEFAULT NULL,
  `parent_id` int(6) DEFAULT NULL,
  `tribe_id` tinyint(1) DEFAULT NULL,
  `player_id` int(5) DEFAULT NULL,
  `alliance_id` int(5) DEFAULT NULL,
  `player_name` varchar(15) DEFAULT NULL,
  `village_name` varchar(35) DEFAULT NULL,
  `alliance_name` varchar(25) DEFAULT NULL,
  `is_capital` tinyint(1) DEFAULT 0,
  `is_special_village` tinyint(1) DEFAULT 0,
  `is_oasis` tinyint(1) DEFAULT NULL,
  `people_count` int(11) DEFAULT 2,
  `crop_consumption` bigint(16) DEFAULT 2,
  `time_consume_percent` float DEFAULT 100,
  `offer_merchants_count` tinyint(4) DEFAULT 0,
  `resources` text DEFAULT NULL,
  `cp` varchar(300) DEFAULT NULL,
  `buildings` text DEFAULT NULL,
  `troops_training` text DEFAULT NULL,
  `troops_num` text DEFAULT NULL,
  `troops_out_num` text DEFAULT NULL,
  `troops_intrap_num` text DEFAULT NULL,
  `troops_out_intrap_num` text DEFAULT NULL,
  `troops_trapped_num` int(11) DEFAULT 0,
  `allegiance_percent` int(11) DEFAULT 100,
  `child_villages_id` text DEFAULT NULL,
  `village_oases_id` text DEFAULT NULL,
  `creation_date` datetime DEFAULT NULL,
  `update_key` varchar(5) DEFAULT NULL,
  `last_update_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `NewIndex2` (`player_id`),
  KEY `NewIndex3` (`is_special_village`),
  KEY `NewIndex4` (`is_oasis`),
  KEY `NewIndex5` (`people_count`),
  KEY `NewIndex1` (`village_name`),
  KEY `NewIndex6` (`player_id`,`is_oasis`)
) ENGINE=InnoDB AUTO_INCREMENT=22501 DEFAULT CHARSET=utf8mb3    


Solution 1:[1]

Is it ENGINE=InnoDB? If not then that can be a big problem. Please provide SHOW CREATE TABLE p_villages

You say id is indexed but is it the PRIMARY KEY. A PRIMARY KEY is, by definition, unique. Hence only one row is involved, and the query should be very fast (a few milliseconds).

Are other queries running at the same time? They could be blocking access to the one row.

Adding RAM, plus increasing innodb_buffer_pool_size won't help much; "3 seconds" is some other problem. What value do you have for that setting?

If id is unique, why do you also test player_id in WHERE v.id='1084' AND v.player_id='1' (There is no problem here, just a puzzle.)

If id is unique, the one of these will succeed, one will fail:

v.id='1084' AND v.player_id='22290'
v.id='1084' AND v.player_id='1'

"everything is indexed" -- The query sets 4 columns; this implies that 4 indexes need to be updated. (Still, this would only take a few extra milliseconds.)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rick James