Reputation: 91
I have written a MYSQL query without much expertise in this area but as my database has increased in size, I'm finding the results are taking far too long to be returned. I can understand why but I can't figure out how to better group my query so that MYSQL isn't searching through the entire database to return the results. I know there is a far more efficient way to do this but I can't figure out how. If I remove the ORDER BY statement, the results are returned in less than a quarter of the time. As it stands now with a table that has 180,000 entries in it (members), it's taking about 4 seconds to return the results.
SELECT members.mem_id, members.username, members.online,
members.dob, members.regdate, members.sex,
members.mem_type, members.aboutme,
geo_cities.name AS city,
geo_countries.name AS country, photos.photo_path
FROM members
LEFT JOIN geo_cities
ON members.cty_id=geo_cities.cty_id
LEFT OUTER JOIN geo_countries
ON geo_cities.con_id=geo_countries.con_id
RIGHT OUTER JOIN photos
ON members.mem_id=photos.mem_id
WHERE (photos.main=1
AND photos.approved=1
AND members.banned!="1"
AND members.profile_photo="1"
AND members.profile_essentials="1"
AND members.profile_user="1")
ORDER BY lastdate DESC
LIMIT 12
Upvotes: 0
Views: 39
Reputation: 108776
It looks like you want to show the most recent 12 members who meet certain criteria.
A few things.
RIGHT JOIN
on photos
is actually an ordinary inner JOIN
: its columns appear in your WHERE
clause.members
and photos
tables.SELECT many columns FROM ... JOIN ... ORDER BY column... LIMIT 12
is a notorious performance antipattern: It constructs a complex result set, then sorts the whole thing, then discards almost all of it. Wasteful.WHERE....members.banned != "1"
Inequality filters like this make SQL work harder (==slower) than equalities. If you can change that to = "0"
or something like that do it.(I guess your lastdate
column is in your members
table, but you didn't tell us that in your question.)
So try something like this to find the twelve members you want to display.
SELECT members.mem_id
FROM members
JOIN photos ON members.mem_id=photos.mem_id
WHERE photos.main=1
AND photos.approved=1
AND members.banned!="1"
AND members.profile_photo="1"
AND members.profile_essentials="1"
AND members.profile_user="1")
ORDER BY lastdate DESC
LIMIT 12
That gets you the ids of the twelve members you want. Use it in your main query.
SELECT members.mem_id, members.username, members.online,
members.dob, members.regdate, members.sex,
members.mem_type, members.aboutme,
geo_cities.name AS city,
geo_countries.name AS country, photos.photo_path
FROM members
LEFT JOIN geo_cities ON members.cty_id=geo_cities.cty_id
LEFT JOIN geo_countries ON geo_cities.con_id=geo_countries.con_id
JOIN photos ON members.mem_id=photos.mem_id
WHERE members.mem_id IN (
SELECT members.mem_id
FROM members
JOIN photos ON members.mem_id=photos.mem_id
WHERE photos.main=1
AND photos.approved=1
AND members.banned!="1"
AND members.profile_photo="1"
AND members.profile_essentials="1"
AND members.profile_user="1")
ORDER BY lastdate DESC
LIMIT 12
)
ORDER BY lastdate DESC
LIMIT 12
This finds the twelve members you care about, then pulls out only their records, instead of pulling all the records.
Then, create a compound index on members(profile_photo, profile_essentials, profile_user, banned, lastdate)
. That compound index will speed up your WHERE
clause a great deal.
Likewise, create a compound index on photos(mem_id, main, approved, photo_path)
.
Things always get exciting when databases start to grow! Read Markus Winand's online book https://use-the-index-luke.com/
Upvotes: 1