![]() |
SQL creates high server load?
For some reason, my host yelled at me because one of my SQL queries was creating too much server load. Is the SQL string inefficient and is something causing it to go longer then it should? I have never ran into a problem with it, but I'm guessing now that there are more rows in my "offer" table it may create more stress.
Quote:
|
Probably, you are just missing some indexes that are needed to bring the query up to a reasonable speed.
At a MINIMUM you need indexes on the following table.fields: -- completed_offers.username -- offers.offerid -- offers.category But having said that... That query sure looks like it is more complex than is needed! Do you really want to return offers.category if the howmany value will be zero? And do you really need to use LIKE in that WHERE countries LIKE ...??PLEASE don't tell me that your contries field is actually a LIST of countries! Please say it isn't something like Austria,Australia,Belgium ... please? |
And will you really have the same offerid in the same category more than once in the offers table???
|
Quote:
Lets tackle these one by one. 1. updated the following: -- completed_offers.username -- Index -- offers.offerid -- Unique Index -- offers.category -- Index 2. Basically the purpose of this whole code is to combine all the categories that are alike and count how many for each and put them into a dropdown 3. My countries are stored as Austria,Australia,Belgium because each row in the 'offers' table has a different set of countries. this was the easiest way. |
Quote:
|
Well, the killer is your bad choice of putting multiple countries into one field. "Easiest" is often not the best in database design, and multi-valued fields are one of the biggest no-nos around. You wouldn't get away with that in any even medium scale corporate operation.
I'm not sure we can fix the performance problem so long as you have that multi-valued field, but we can at least make a stab at it. You missed answering one question: > Do you really want to return offers.category if the howmany value will be zero? though I'm not sure it makes much performance difference. *MAYBE* this query will be more efficient than yours. No promises. That countries LIKE is still a killer.Code:
$sql = "SELECT OS.category, IFNULL(SS.thecount, 0) AS howmany "AND C.offerid IS NULL turns it into a sort of reverse INNER JOIN.And since I was then doing that as a LEFT JOIN, it made sense to move the counting "down" one level, thus avoiding the need for the COUNT(DISTINCT ...) (also an expensive operation).That's all the tricks I can see, assuming I got the query right, short of normalizing you DB design. |
Wow! That ABSOLUTELY cut the time down! It took it from about 7-10 seconds down to 1-2! You rock! Also, yes. I want to return the offers.category if the howmany value will be zero :)
EDIT: I take that back. It didn't work. Take a look at what it SHOULD look like, as apposed to what your new query does: After: http://puu.sh/1deKd Before: http://puu.sh/1deKK |
Ahhh...yes, I see that.
The problem occurs because, again, your DB isn't normalized. If it were, you would have a separate CATEGORIES table, where each category had a categoryid (INT PRIMARY KEY) and cateogoryname. And then, in your OFFERS table, you would use the categoryid instead of the name. You really should read up on NORMALIZATION. Your lack of it is causing you all sorts of efficiency griefs. So lacking that separate CATEGORIES table... We could fix it by just changing the first SELECT to SELECT DISTINCT, but that won't be efficient. So try this... Code:
$sql = "SELECT OS.category, IFNULL(SS.thecount, 0) AS howmany "SELECT DISTINCT category FROM offers is, essentially, building the missing CATEGORIES table. But it's a much more expensive operation than if you actually had such a table. |
Truly, if your DB were completely normalize with proper indexes, I wouldn't expect this query to take more than 200 milliseconds in MySQL given the apparent number of records you seem to have.
|
As I see it you need these tables:
Code:
CREATE TABLE Categories (The syntax there for the foreign keys isn't quite correct for MySQL, but it's a compact form that easy to read for a post like this. |
I don't quite understand how those tables would work. How would i store the list of countries per offer in a country category? If you wanted a new row for each, that would be a LOT of rows. Give me an example of each table with a test row?
|
Code:
CategoriesA query such as yo were doing in your existing tables would probably be done as: Code:
SELECT C.catname, IFNULL(thecount,0) AS howmanyHmmm.... I guess that would be Code:
SELECT C.catname, IFNULL(thecount,0) AS howmanyTHAT QUERY WOULD BE FAST, assuming that all of the foreign keys were themselves indexes. |
So what kind of performance did you get from the query in my post #8?
I forgot to mention something: A condition that uses LIKE can *NOT* use an index, except in the specialized case of WHERE field LIKE 'xxx%'That is, where the only % wild card character is at the end of the string to match via LIKE. So your query is FORCING MySQL to do a COMPLETE scan of the entire OFFERS table. And that's why it's slow. And why it would be hard to make it faster. |
Quote:
|
Quote:
The important thing is to normalize the data. A lot of rows in a table is 50,000,000 and even then that isn't really a lot. Properly tuned databases with good indexes for the type of queries being ran, with normalized data and optimized queries are important. The number of rows, significantly less important. |
| All times are GMT +1. The time now is 12:20 PM. |
Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.