Улучшить производительность запроса с большой таблицей? - PullRequest
0 голосов
/ 04 октября 2018

У меня есть большая таблица с именем 'roomlogs', в которой содержится почти 1 миллион записей.Структура таблицы:

id -> PK

roomId -> varchar FK для таблицы комнат

userId -> varchar FK для таблицы пользователей

enterTime -> Дата и время

exitTime -> Дата и время

статус -> bool

У меня есть предыдущийиндексируя номер комнаты, я недавно добавил индекс для столбца 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 ;

Что может быть причиной того, что это заняло так много времени:

  1. Недавно я добавил индекс, поэтому предыдущие строки не были проиндексированы.
  2. В настоящее время нет выбора типа хранилища для каких-либо индексов.Должен ли я изменить его на B-дерево?
  3. На моем веб-сайте я получаю 20-30 одновременных вызовов на другие процедуры, в то время как эта процедура имеет 10-20 одновременных вызовов, выполняет ли запрос на обновление в процедуре блокировку?Но в таблице MySQL.slow_logs для каждого запроса блокировка _time показывает 0.
  4. Есть ли другие причины для такого поведения?

Редактировать: Вот ТАБЛИЦА ШОУ:

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 или создает запрос на обновление, потому что я вижу, что, когда хранимая выше процедура выполняется больше раз, чем этот запросбольше времени.

Вот ссылка для переменных MySQL: https://docs.google.com/document/d/17_MVaU4yvpQfVDT83yhSjkLHsgYd-z2mg6X7GwvYZGE/edit?usp=sharing

1 Ответ

0 голосов
/ 05 октября 2018

roomlogs нужен этот «составной» индекс:

INDEX(userId, `status`, enterTime)

Я недавно добавил индекс, чтобы предыдущие строки не были проиндексированы.

Не верно.Добавление INDEX индексирует всю таблицу.

Тип индекса по умолчанию: BTree;нет необходимости явно указывать его.

делает ли запрос на обновление в процедуре блокировку?

Он выполняет некоторую форму блокировки.Какова стоимость autocommit?Вы явно используете BEGIN и COMMIT?Таблица ENGINE=InnoDB?Пожалуйста, предоставьте SHOW CREATE TABLE.

MySQL.slow_logs таблицу для каждого запроса, который показывает _time 0. 0. 1027 *

Отображаемое INSERT, кажется, вставляет одну и ту же строкукак UPDATE.Может быть, вам нужно INSERT ... ON DUPLICATE KEY UPDATE ...?

Не «скрывать индексный столбец в функции»;вместо DATEDIFF(roomlogs.enterTime,NOW()) = 0, do

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

Это позволяет более полно использовать индекс.

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

Буферный пул всего в 97 517 568 - сделайте его больше похожим на 9G.

...