提高大表查询的性能?

42fyovps  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(289)

我有一个名为“roomlogs”的大表,它有将近100万个条目。表的结构:
id-->主键
roomid-->varchar fk到rooms表
userid-->varchar fk to users表
输入时间-->日期和时间
exittime-->日期和时间
状态-->布尔
我以前在roomid上做过索引,最近在userid列上添加了索引。
所以,当我用下面的代码运行存储过程时,它需要更多的时间,比如平均50秒。这是不应该的。

DELIMITER ;;
    CREATE DEFINER=`root`@`%` PROCEDURE `enter_room`(IN pRoomId varchar(200), IN puserId varchar(50), IN ptime datetime, IN phidden int, pcheckid int, pexit datetime)

begin
    update roomlogs set 
          roomlogs.exitTime = ptime,
          roomlogs.`status` = 1  
       where 
              roomlogs.userId = puserId 
          and roomlogs.`status` = 0 
          and DATEDIFF(ptime,roomlogs.enterTime) = 0;

    INSERT into roomlogs 
      ( roomlogs.roomId,
        roomlogs.userId,
        roomlogs.enterTime,
        roomlogs.exitTime,
        roomlogs.hidden,
        roomlogs.checkinId ) 
      value
      ( pRoomId,
        userId,
        ptime,
        pexit,
        phidden,
        pcheckid);

    select * 
       from 
          roomlogs 
       where 
          roomlogs.id= LAST_INSERT_ID();
    end ;;
    DELIMITER ;

为什么要花这么多时间:
我最近添加了一个索引,所以前面的行没有索引。
目前没有为任何索引选择存储类型。我应该把它改成b树吗?
在我的网站上,我得到20-30对其他程序的同时调用,而这个程序有10-20个同时调用,程序中的更新查询是否锁定?但是在mysql.slow\u logs表中,每个查询的锁时间都显示为0。
这种行为还有其他原因吗?
编辑:以下是显示表格:

CREATE TABLE `roomlogs` (
   `roomId` varchar(200) CHARACTER SET latin1 DEFAULT NULL,
   `userID` varchar(50) CHARACTER SET latin1 DEFAULT NULL,
   `enterTime` datetime DEFAULT NULL,
   `exitTime` datetime DEFAULT NULL,
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `status` int(11) DEFAULT '0',
   `hidden` int(11) DEFAULT '0',
   `checkinId` int(11) DEFAULT '-1',
   PRIMARY KEY (`id`),
   KEY `RoomLogIndex` (`roomId`),
   KEY `RoomLogIDIndex` (`id`),
   KEY `USERID` (`userID`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1064216 DEFAULT CHARSET=utf8

我还可以看到这个查询的运行次数越来越多,比如每天100000次(几乎是连续的)。

SELECT count(*) from roomlogs where roomId=proomId and status='0';

因为这个查询是从同一个表中读取的,所以innodb会在update查询上阻塞或创建锁吗?因为我可以看到,当上面的存储过程运行更多次时,这个查询会花费更多的时间。
以下是mysql变量的链接:https://docs.google.com/document/d/17_mvau4yvpqfvdt83yhsjklhsgyd-z2mg6x7gwvyzge/edit?usp=sharing

i2loujxw

i2loujxw1#

roomlogs 需要此“综合”索引:

INDEX(userId, `status`, enterTime)

我最近添加了一个索引,所以前面的行没有索引。
不是真的。添加 INDEX 索引整个表。
默认索引类型为 BTree ; 无需明确指定。
过程中的update查询是否锁定?
它可以进行某种形式的锁定。它的价值是什么 autocommit ? 你明确使用 BEGIN 以及 COMMIT ? table在哪 ENGINE=InnoDB ? 请提供 SHOW CREATE TABLE .
slow\u logs表对于每个查询,lock\u time显示为0。
这个 INSERT 您的节目似乎插入了与 UPDATE . 也许你需要 INSERT ... ON DUPLICATE KEY UPDATE ... ?
不要“在函数中隐藏索引列”;而不是 DATEDIFF(roomlogs.enterTime,NOW()) = 0 ,做

AND enterTime >= CURDATE()
AND enterTime  < CURDATE() + INTERVAL 1 DAY

这样可以更充分地使用索引。

KEY `RoomLogIndex` (`roomId`),  Change to  (roomId, status)
KEY `RoomLogIDIndex` (`id`),    Remove, redundant with the PK

仅97517568中的缓冲池—使其更像9g。

相关问题