Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 467897
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T23:37:40+00:00 2026-05-12T23:37:40+00:00

The following query is pretty simple. It selects the last 20 records from a

  • 0

The following query is pretty simple. It selects the last 20 records from a messages table for use in a paging scenario. The first time this query is run, it takes from 15 to 30 seconds. Subsequent runs take less than a second (I expect some caching is involved). I am trying to determine why the first time takes so long.

Here’s the query:

SELECT DISTINCT ID,List,`From`,Subject, UNIX_TIMESTAMP(MsgDate) AS FmtDate
FROM messages
WHERE List='general'
ORDER BY MsgDate
LIMIT 17290,20;

MySQL version: 4.0.26-log

Here’s the table:

messages  CREATE TABLE `messages` (
  `ID` int(10) unsigned NOT NULL auto_increment,
  `List` varchar(10) NOT NULL default '',
  `MessageId` varchar(128) NOT NULL default '',
  `From` varchar(128) NOT NULL default '',
  `Subject` varchar(128) NOT NULL default '',
  `MsgDate` datetime NOT NULL default '0000-00-00 00:00:00',
  `TextBody` longtext NOT NULL,
  `HtmlBody` longtext NOT NULL,
  `Headers` text NOT NULL,
  `UserID` int(10) unsigned default NULL,
  PRIMARY KEY  (`ID`),
  UNIQUE KEY `List` (`List`,`MsgDate`,`MessageId`),
  KEY `From` (`From`),
  KEY `UserID` (`UserID`,`List`,`MsgDate`),
  KEY `MsgDate` (`MsgDate`),
  KEY `ListOnly` (`List`)
) TYPE=MyISAM ROW_FORMAT=DYNAMIC

Here’s the explain:

table   type    possible_keys  key       key_len  ref       rows  Extra
------  ------  -------------  --------  -------  ------  ------  --------------------------------------------
m       ref     List,ListOnly  ListOnly  10       const    18002  Using where; Using temporary; Using filesort

Why is it using a filesort when I have indexes on all the relevant columns? I added the ListOnly index just to see if it would help. I had originally thought that the List index would handle both the list selection and the sorting on MsgDate, but it didn’t. Now that I added the ListOnly index, that’s the one it uses, but it still does a filesort on MsgDate, which is what I suspect is taking so long.

I tried using FORCE INDEX as follows:

SELECT DISTINCT ID,List,`From`,Subject, UNIX_TIMESTAMP(MsgDate) AS FmtDate
FROM messages
FORCE INDEX (List)
WHERE List='general'
ORDER BY MsgDate
LIMIT 17290,20;

This does seem to force MySQL to use the index, but it doesn’t speed up the query at all.

Here’s the explain for this query:

table   type    possible_keys  key     key_len  ref       rows  Extra                       
------  ------  -------------  ------  -------  ------  ------  ----------------------------
m       ref     List           List    10       const    18002  Using where; Using temporary

UPDATES:

I removed DISTINCT from the query. It didn’t help performance at all.

I removed the UNIX_TIMESTAMP call. It also didn’t affect performance.

I made a special case in my PHP code so that if I detect the user is looking at the last page of results, I add a WHERE clause that returns only the last 7 days of results:

SELECT m.ID,List,From,Subject,MsgDate
FROM messages
WHERE MsgDate>='2009-11-15'
ORDER BY MsgDate DESC
LIMIT 20

This is a lot faster. However, as soon as I navigate to another page of results, it must use the old SQL and takes a very long time to execute. I can’t think of a practical, realistic way to do this for all pages. Also, doing this special case makes my PHP code more complex.

Strangely, only the first time the original query is run takes a long time. Subsequent runs of either the same query or a query showing a different page of results (i.e., only the LIMIT clause changes) are very fast. The query slows down again if it has not been run for about 5 minutes.

SOLUTION:

The best solution I came up with is based on Jason Orendorff and Juliet’s idea.

First, I determine if the current page is closer to the beginning or end of the total number of pages. If it’s closer to the end, I use ORDER BY MsgDate DESC, apply an appropriate limit, then reverse the order of the returned records.

This makes retrieving pages close to the beginning or end of the resultset much faster (first time now takes 4-5 seconds instead of 15-30). If the user wants to navigate to a page near the middle (currently around the 430th page), then the speed might drop back down. But that would be a rare case.

So while there seems to be no perfect solution, this is much better than it was for most cases.

Thank you, Jason and Juliet.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T23:37:40+00:00Added an answer on May 12, 2026 at 11:37 pm

    Instead of ORDER BY MsgDate LIMIT 17290,20, try ORDER BY MsgDate DESC LIMIT 20.

    Of course the results will come out in the reverse order, but that should be easy to deal with.

    EDIT: Do your MessageId values always increase with time? Are they unique?

    If so, I would make an index:

    UNIQUE KEY `ListMsgId` ( `List`, `MessageId` )
    

    and query based on the message ids rather than the date when possible.

    -- Most recent messages (in reverse order)
    SELECT * FROM messages
    WHERE List = 'general'
    ORDER BY MessageId DESC
    LIMIT 20
    
    -- Previous page (in reverse order)
    SELECT * FROM messages
    WHERE List = 'general' AND MessageId < '15885830'
    ORDER BY MessageId DESC
    LIMIT 20
    
    -- Next page
    SELECT * FROM messages
    WHERE List = 'general' AND MessageId > '15885829'
    ORDER BY MessageId
    LIMIT 20
    

    I think you’re also paying for having varchar columns where an int type would be a lot faster. For example, List could instead be a ListId that points to an entry in a separate table. You might want to try it out in a test database to see if that’s really true; I’m not a MySQL expert.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

For the following pretty straightforward task: query a list of products from a DB
I have the following piece of code, executing a pretty simple MySQL query: $netnestquery
I have the following pretty simple linq query querying a linq to entities edmx.
I'm starting to use Simple.Data a bit more seriously and have the following scenario
The following query: SELECT DISTINCT ClassName FROM SiteTree ORDER BY ClassName is returning things
I have the following SQL query: select AuditStatusId from dbo.ABC_AuditStatus where coalesce(AuditFrequency, 0) <>
I have the following query: SELECT src_big, created, modified, owner, aid, caption FROM photo
I'm trying to run a query on a very simple table but I'm not
Following query is used for Getting Categories and one news for each category. How
The following query returns strange results for me: SELECT `Statistics`.`StatisticID`, COUNT(`Votes`.`StatisticID`) AS `Score`, COUNT(`Views`.`StatisticID`)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.