Вряд ли есть необходимость брать весь диалог, из-за возможности встречающихся ключевых слов в процессе разговора, не относящихся к сути обращения.
Имеет смысл взять только первое сообщение от клиента, в котором он излагал суть обращения. А значит сократить объем обрабатываемых данных. Если нет, то не сильно это усложнит обработку, если обрабатывать все сообщения, даже если их миллионы - Это же одиночная обработка. Дальше вы будуте обрабатывать новые входящие обращения на лету. Значит:
1. Выбрать первые сообщения всех диалогов из БД. (можно с использованием limit и пометкой после обработки, что этот диалог уже обработан).
2. Циклом пробегаетесь по всем полученным данным. Внутри цикла foreach с массивом ключевых слов а внутри foreach функция stripos(). если есть совпадение с ключевым словом - кидаем в массив совпадений ID диалога и ID ключевого слова.
3. После прохождения всех диалогов. Записываете в отдельную таблицу ID диалогов и ключевых слов одним запросом.
Далее все новые вопросы обрабатываете таким же способом. А список диалогов получаете так же как и получали, но уже с использованием JOINа к новой таблице, чтобы вывести соответствующие пометки