Как оптимизировать подобный sql?
Если проблема точно в этом запросе, можно попробовать разделить запрос на две части без использования 
инструкции ON DUPLICATE KEY UPDATE:if exists(select 1
             from chat_lastread
            where `user_id`   = #user_id
              and `dialog_id` =  #dialog_id)
 begin
   update chat_lastread
      set `date` = NOW()
     from chat_lastread
    where `user_id`   = #user_id
      and `dialog_id` =  #dialog_id
 end
 else
 begin
   INSERT INTO chat_lastread (
     `user_id`,
     `dialog_id`,
     `date`
   ) VALUES(
     #user_id,
     #dialog_id,
     NOW()
   )
 end
`dialog_id` int(16) NOT NULL, - 16 отображаемых знаков - тут вроде не должно быть так, там может быть максимум (11) при int, и емнип в любом случае размер отводимой памяти будет 4 байта. Если вы планируете хранить более 4 миллиардов записей используйте bigint.