Mysql Update查询耗费了大量时间

时间:2016-05-22 06:48:52

标签: mysql galera

我有一个mysql表,在这个表上有一列(numviews),它经常更新(相同的更新查询在循环中运行)。它需要花费大量时间超过2秒,我无法找到如何改进这一点,因为它影响/减慢我的应用程序也依赖于此表。这是mysql表。

注意:它是一个innodb表,没有其他慢查询。此表位于mariadb galera集群下。我也有 300 最大连接数。在任何时候,全球联系都不会超过170/180。

CREATE TABLE `data_table` (
  `site` VARCHAR(100) NOT NULL DEFAULT '',
  `active` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
  `numclicks` INT(10) UNSIGNED NOT NULL DEFAULT '0',
  `numviews` INT(20) UNSIGNED NOT NULL DEFAULT '0',
  `country` VARCHAR(200) DEFAULT NULL,
  `viewcount` INT(10) UNSIGNED NOT NULL DEFAULT '0',
  `name` VARCHAR(150) NOT NULL DEFAULT '',
  `comments` TEXT NOT NULL,
  `boost` FLOAT DEFAULT '0',
  `daily_limit` INT(11) DEFAULT '0',
  PRIMARY KEY (`site`)
) ENGINE=INNODB DEFAULT CHARSET=latin1

这是在循环上运行的mysql更新查询(在该表上运行的查询大约是以下查询的50倍)。

UPDATE data_table  set numviews = numviews + 1 where site='xyz';

Query OK, 1 row affected (2.57 sec)
Rows matched: 1  Changed: 1  Warnings: 0


SELECT site,active,numclicks,numviews,country,viewcount FROM data_table WHERE site='xyz'\G
*************************** 1. ROW ***************************
                    site: xyz
                  active: 1
               numclicks: 130406
                numviews: 48962
                 country: |xx yy |
               viewcount: 134022

编辑:我也可以看到一些死锁。

------- TRX HAS BEEN WAITING 2 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 3020 page no 10 n bits 120 index `PRIMARY` of table `data_table`trx table locks 1 total table locks 47  trx id 71211631903 lock_mode X locks rec but not gap waiting lock hold time 2 wait time before grant 0
------------------
---TRANSACTION 71211631885, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 1083597, OS thread handle 0x7f782a335700, query id 184464304 machine1 XX.XX.XX.XX user updating
UPDATE data_table set numviews = numviews + 1 where site='xyz'
Trx #rec lock waits 12 #table lock waits 0
Trx total rec lock wait time 12 SEC
Trx total table lock wait time 0 SEC
------- TRX HAS BEEN WAITING 2 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 3020 page no 10 n bits 120 index `PRIMARY` of table `data_table` trx table locks 1 total table locks 47  trx id 71211631885 lock_mode X locks rec but not gap waiting lock hold time 2 wait time before grant 0
------------------
---TRANSACTION 71211631883, ACTIVE 2 sec
mysql tables in use 1, locked 1
2 lock struct(s), heap size 360, 1 row lock(s), undo log entries 1
MySQL thread id 1082885, OS thread handle 0x7f713e848700, query id 184464302 xxx XX.XX.XX.XX user query end
UPDATE data_table set numviews = numviews + 1 where site='xyz'
Trx #rec lock waits 225 #table lock waits 0
Trx total rec lock wait time 366 SEC
Trx total table lock wait time 0 SEC

任何人都可以帮我改进此更新查询吗?

3 个答案:

答案 0 :(得分:0)

您实际上并不需要这样做,您要做的是更新列或增加num_views列。我的意思是,假设您循环1000次并执行UPDATE;而是执行单个update,其值1000表示set numviews = 1000 + 1(OR),换句话说,如果您拥有总观看次数值,则可以执行单UPDATE次操作。如果是这样,那么下面的代码将执行相同的

UPDATE data_table set numviews = total_views + 1 where site='xyz';

答案 1 :(得分:0)

快速更改的计数器(点击次数,视图)应位于单独的表格中。这样,不需要这些列的查询(读取和写入)就不会干扰它们。

从任何交易中删除UPDATE - 将其作为自己的交易。

您的Galera节点相隔多远?如果它们是100ms的越野,则每秒只能进行10次这样的更新。如果是你的情况,请阅读我的high speed ingestion blog;然后我们可以讨论如何在Galera上使用MyISAM来提高UPDATEs的吞吐量。

答案 2 :(得分:-1)

确保站点列具有索引,或者如果您可以按ID而不是名称确定站点,则可以更好地改进它。创建ID并将其设置为主键。此外,如果只有一个站点,您可以使用LIMIT 1进行一些改进。但是我不确定。也许您可以使用PDO来改进它,以便在循环运行时使用不同的值准备相同的请求。