Home > database >  optmize a select query (if necessary creating index)
optmize a select query (if necessary creating index)

Time:08-03

I have 2 tables:

chats (id, ..., chat_status_id) // (about 28k records)
chat_messages(id, chat_id, send_date, ...) // (about 1 million records)

I need to get chats of certain status with latest message.

This is the select I am using, but it's pretty slow (it works in the end):

SELECT c.*,
       p1.*
FROM   chats c
       JOIN chat_messages p1
         ON ( c.id = p1.chat_id )
       LEFT OUTER JOIN chat_messages p2
                    ON ( c.id = p2.chat_id
                         AND ( p1.send_date < p2.send_date
                                OR ( p1.send_date = p2.send_date
                                     AND p1.id < p2.id ) ) )
WHERE  p2.id IS NULL
AND c.chat_status_id = 1
ORDER  BY p1.send_date DESC 

I do not know howto optimize it.

CodePudding user response:

I would start with a few index updates. First, your WHERE clause is based on the CHATS table status, that should be first in your index order, but can have the ID as well AFTER to support the joins. Next, your messages table. Similarly, those are JOINed based on the CHAT ID, not its own unique table ID as the primary consideration, but does use the ID as the carry-along for conditional testing of p1.id < p2.id. Suggestions as follows.

Table          Index
Chats          ( Chat_Status_Id, id )
Chat_Messages  ( Chat_id, id, send_date )

CodePudding user response:

Give this a try:

SELECT  c.*, p1.*
    FROM  chats c
    JOIN  chat_messages p1  ON ( c.id = p1.chat_id )
    WHERE  NOT EXISTS 
    (
        SELECT  1
            FROM  chat_messages p2
            WHERE  c.id = p2.chat_id
              AND  ( p1.send_date < p2.send_date
                      OR  ( p1.send_date = p2.send_date
                              AND  p1.id < p2.id ) ) 
    )
    WHERE  c.chat_status_id = 1
    ORDER BY  p1.send_date DESC 

With

chats:  INDEX(chat_status_id, id)
chat_messages:  INDEX(chat_id, send_date,  id)
  • Related