-1

我有一个 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

谁能帮我改进这个更新查询?

4

3 回答 3

0

快速变化的计数器(点击次数、浏览次数)应该在单独的表格中。这样,不需要这些列的查询(读取和写入)不会干扰它们。

从任何事务中删除它UPDATE——将其作为自己的事务进行。

您的 Galera 节点相距多远?如果它们以 100 毫秒的速度跨越国家,那么您每秒只能进行 10 次这样的更新。如果这是您的情况,请阅读我的高速摄取博客;然后我们可以讨论如何在 Galera 上使用 MyISAM 来提高您的UPDATEs.

于 2016-05-27T23:18:28.273 回答
0

您实际上并不需要它,您要做的是更新列或增加num_views列。我的意思是,假设您循环 1000 次并执行UPDATE; 而是执行一个update值为 1000的单次操作set numviews = 1000 + 1(或),换句话说,如果您事先掌握了视图总数的值,则可以执行单次UPDATE操作。如果是这样,那么下面的代码也会做同样的事情

UPDATE data_table set numviews = total_views + 1 where site='xyz';
于 2016-05-22T06:58:44.537 回答
-1

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

于 2016-05-22T06:56:04.680 回答