Skip to main content
Inspiring
February 11, 2011
Question

MySQL slow queries

  • February 11, 2011
  • 6 replies
  • 1955 views

I have been trying to reduce loading speed of my pages because, apparently mysql server is experiencing some difficulties due to number of queries on the same page!? Frankly, I am not 100% sure that the number of queries is actually causing the slowness with my application, but it's pretty annoying given that the page takes like 8 seconds or something to load.

Now, there is about 11000 records (20mb) in the table, it's definitely not a lot to handle for MYSQL server, however all queries are executed when accessing the page (this is normal of course), pulling data simultaneously from the same table...

Anyway take a look at queries:

------------11000 records------------

<cfquery name="maintable" datasource="datasource">
SELECT *
FROM maintable
WHERE CATEGORY = "1"
ORDER BY DATE DESC , id DESC
</cfquery>

<cfquery name="free" datasource="datasource">
SELECT *
FROM maintable
WHERE buy = "Free" AND CATEGORY = "1"
ORDER BY HITS DESC
</cfquery>

<cfquery name="buy" datasource="datasource">
SELECT *
FROM maintable
WHERE buy = "withprice" AND CATEGORY = "1"
ORDER BY HITS DESC
</cfquery>

------------400 records------------

<cfquery name="news" datasource="datasource">
SELECT *
FROM news
WHERE CATEGORY = "1"
ORDER BY DATE DESC
</cfquery>

------------300 records------------

<cfquery name="tuts" datasource="datasource">
SELECT *
FROM tuts
WHERE CATEGORY = "1"
ORDER BY DATE DESC
</cfquery>


also for now only the primary key is assigned to id/s, but I am thinking on adding one more index for category in the  maintable!? On the other hand, this may not be a good idea simply because from 11000 records about 8000 of them are in category 1, so basically queries will have to process about 70+% of all records which can result in even slower loading!?

how to speed things up? guys, I would really appreciate your help on this one.

    This topic has been closed for replies.

    6 replies

    pirula08Author
    Inspiring
    February 14, 2011

    Ok, I spent the last two days reading bunch of articles about MySQL database optimization on the internet in order to address this issue more efficiently. Honestly, it was not easy at all, but the effort definitely paid off since the slowness is gone.

    Thanks guys, I couldn't do it without you Here is what I came up with mostly because of your suggestions that were more than helpful and absolutely in place. yeah, I can see that now.

    - VARCHAR sizes have been reduced by 70 percent
    - date is, well DATE now
    - I realized that the four columns can be completely removed, one has already  been  deleted, one, as Owain North suggested will be moved to a separate table while the remaining two will be deleted as soon as possible given the number of pages on which the code must be adjusted first. This should improve the overal performance a bit more.
    - 3 indexes have been added. Adding indexes noticeably reduced the number of scanned rows.
    - I will never again use a freaking star (*) on my keybord
    - LIMITs have been added in queries where only 10 records should be displayed

    anyway, check out the timings

    Runtime: 172ms          Runtime: 188ms     Runtime: 322ms
    Runtime: 0ms            Runtime: 31ms      Runtime: 78ms
    Runtime: 0ms            Runtime: 0ms       Runtime: 16ms
    Runtime: 16ms           Runtime: 18ms      Runtime: 0ms
    Runtime: 16ms           Runtime: 0ms       Runtime: 0ms

    after these modifications, fully equipted page with CSS, javascript etc. takes only 3 seconds to load which is a significant improvement over initial 8-9

    Owainnorth
    Inspiring
    February 15, 2011

    Success!

    People often underestimate quite how much difference the database design makes, but a poorly designed one really can ruin an entire application.

    You've seen that now, so next time you'll be the one lecturing other people on how it should be done

    Glad to hear you got it sorted.

    O.

    pirula08Author
    Inspiring
    February 14, 2011

    Ok, I spent the last two days  reading bunch of articles about MySQL database optimization on the  internet in order to address this issue more efficiently. Honestly, it  was not easy at all, but the effort definitely paid off since the  slowness is gone.

    Thanks guys, I couldn't do it without you Here is what I came up with mostly because of your suggestions that  were more than helpful and absolutely in place. yeah, I can see that  now.

    - VARCHAR sizes have been reduced by 70 percent
    - date is, well DATE now
    -  I realized that the four columns can be completely removed, one has  already  been  deleted, one, as Owain North suggested will be moved to a  separate table while the remaining two will be deleted as soon as  possible given the number of pages on which the code must be adjusted  first. This should improve the overal performance a bit more.
    - 3 indexes have been added. Adding indexes noticeably reduced the number of scanned rows.
    - I will never again use a freaking star (*) on my keybord
    - LIMITs have been added in queries where only 10 records should be displayed

    anyway, check out the timings

    Runtime: 172ms          Runtime: 188ms     Runtime: 322ms
    Runtime: 0ms            Runtime: 31ms      Runtime: 78ms
    Runtime: 0ms            Runtime: 0ms       Runtime: 16ms
    Runtime: 16ms           Runtime: 18ms      Runtime: 0ms
    Runtime: 16ms           Runtime: 0ms       Runtime: 0ms

    after  these modifications, fully equipted page with CSS, javascript etc.  takes only 3 seconds to load which is a significant improvement over  initial 8-9

    BKBK
    Community Expert
    Community Expert
    February 12, 2011

    What happens when you

    1) create an index on category for each of the tables maintable, news and tuts

    2) get data from existing result set by means of query of a query, as follows

    <cfquery name="data" datasource="datasource">
    SELECT *
    FROM maintable
    WHERE CATEGORY = "1"
    </cfquery>

    <cfquery name="dataByDate" dbtype="query">
    SELECT *
    FROM data
    ORDER BY DATE DESC , id DESC
    </cfquery>

    <cfquery name="free" dbtype="query">
    SELECT *
    FROM data
    WHERE buy = "Free"
    ORDER BY HITS DESC
    </cfquery>

    <cfquery name="buy" dbtype="query">
    SELECT *
    FROM data
    WHERE buy = "withprice"
    ORDER BY HITS DESC
    </cfquery>

    pirula08Author
    Inspiring
    February 14, 2011

    Ok, I spent the last two days reading bunch of articles about MySQL database optimization on the internet in order to address this issue more efficiently. Honestly, it was not easy at all, but the effort definitely paid off since the slowness is gone.

    Thanks guys, I couldn't do it without you Here is what I came up with mostly because of your suggestions that were more than helpful and absolutely in place. yeah, I can see that now.

    - VARCHAR sizes have been reduced by 70 percent
    - date is, well DATE now
    - I realized that the four columns can be completely removed, one has already  been  deleted, one, as Owain North suggested will be moved to a separate table while the remaining two will be deleted as soon as possible given the number of pages on which the code must be adjusted first. This should improve the overal performance a bit more.
    - 3 indexes have been added. Adding indexes noticeably reduced the number of scanned rows.
    - I will never again use a freaking star (*) on my keybord
    - LIMITs have been added in queries where only 10 records should be displayed

    anyway, check out the timings

    Runtime: 172ms          Runtime: 188ms     Runtime: 322ms
    Runtime: 0ms            Runtime: 31ms      Runtime: 78ms
    Runtime: 0ms            Runtime: 0ms       Runtime: 16ms
    Runtime: 16ms           Runtime: 18ms      Runtime: 0ms
    Runtime: 16ms           Runtime: 0ms       Runtime: 0ms

    after these modifications, fully equipted page with CSS, javascript etc. takes only 3 seconds to load which is a significant improvement over initial 8-9

    Inspiring
    February 12, 2011

    I think you are hurting yourself by only supplying us with the bare minimum of information and forgetting important things like that there are cfqueryparams involved and that you only really need 10 records. Why don't you just enable debugging on your CF server and post a dump of the debug output here, together with the actual code?

    Further, your design is hurting you. You say 11000 records is 20 MB, so 8000 records is 16 MB. Over a 100 Mbit/s network that takes 1.5 seconds just to transport from MySQL to CF. If you need to display 10 records, then download 10 records from the database to CF. An index on category is not going to help you since it is not selective enough. A composite index on category and buy may help, but only if you add hits to it as well so it helps to avoid the sort that has to happen for your free and buy queries.

    Inspiring
    February 11, 2011

    In addition to Adam's answer, ask yourself the following questions:

    Do you really need all those records every single time, or are there further constraints you can add to your where clause?

    What are you doing with the data after you get it?

    Why are you only selecting from one table at a time?

    pirula08Author
    Inspiring
    February 11, 2011

    Do you really need all those records every single time, or are there further constraints you can add to your where clause? What are you doing with the data after you get it?

    ok, the first query outputs all ebooks in the database and displays 10 records per page,

    pages:   1,2,3,4,5,6,7,8,9,10..... next page I last page (800 or so)

    I can also make something like this, limit output to say 300 (...ORDER BY DATE DESC , id DESC LIMIT 300) and than I would have

    pages:   1,2,3,4,5,6,7,8,9,10..... next page I last page (30) I see all ebooks

    however, I'm not sure that this will boost the loading speed

    the second shows the 10 most downloaded free ebooks while the third one displays the 10 most downloaded ebooks with a price

    Why are you only selecting from one table at a time?

    because that table has all the information about ebooks in it. there are also news, tuts,reviews tables

    Inspiring
    February 11, 2011

    You should experiment with the indexes anyhow.  And also consider indexing the cols you're ordering on.

    Also, and most importantly, don't use SELECT * unless you really really want every column to be returned.  If not, specify which columns you want.

    Are categories always numeric values?  If so, making the column a numeric (like a LONG, probably) would improve things a bit.

    How do these queries perform if you run them in a dedicated MySQL client tool?  Is it definitely the queries that are bogging you down?

    Is there anything on MySQL which will do an explain path for you, to see if there's any elements of the query execution which is slow?

    --

    Adam

    pirula08Author
    Inspiring
    February 11, 2011

    don't use SELECT * unless you really really want every column to be returned.

    I need every column to be returned!

    Are categories always numeric values?

    Actually, none of them is! Here are the correct info on categories: ebooks, VARCHAR(45). also most of the columns are set to VARCHAR, even DATE.

    sorry about that, I was at university when I wrote this and I did it in a hurry

    How do these queries perform if you run them in a dedicated MySQL client tool?

    everything is perfect, as far as I can see.

    Is it definitely the queries that are bogging you down?

    yep, I also tried to run the page only with those queries, without any other code, just queries not even cfoutputs! Unfortunately, the result was the same

    Is there anything on MySQL which will do an explain path for you, to see
    if there's any elements of the query execution which is slow?

    i also tried with this command  EXPLAIN SELECT * FROM maintable WHERE CATEGORY = 'ebooks';

           everything looks fine and here is the result

           id     table           TYPE   possible_keys   key     key_len    ref   rows     extra

           1      maintable     All                                                               8041    using where