Very slow MySql queries Joomla 2.5 - php

My website is experiencing very slow queries like the one below. It is Joomla 2.5.
# Query_time: 19.797091 Lock_time: 0.000561 Rows_sent: 12 Rows_examined: 4127
SET timestamp=1385467501;
SELECT a.fulltext, a.id, a.title, a.alias, a.title_alias, a.introtext, a.state, a.catid, a.created, a.created_by, a.created_by_alias,a.images, a.modified, a.modified_by,a.publish_up, a.publish_down, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.featured, LENGTH(a.fulltext) AS readmore,a.fulltext, a.id, a.title, a.alias, a.title_alias, a.introtext, a.state, a.catid, a.created, a.created_by, a.created_by_alias,a.images, a.modified, a.modified_by,a.publish_up, a.publish_down, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.featured, LENGTH(a.fulltext) AS readmore,c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias,CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author,ua.email AS author_email,contact.id as contactid,parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias,ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count,c.published, CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published
FROM j25_content AS a
LEFT JOIN j25_content_frontpage AS fp ON fp.content_id = a.id
LEFT JOIN j25_categories AS c ON c.id = a.catid
LEFT JOIN j25_users AS ua ON ua.id = a.created_by
LEFT JOIN j25_users AS uam ON uam.id = a.modified_by
LEFT JOIN (
SELECT contact.user_id, MAX(contact.id) AS id, contact.language
FROM j25_contact_details AS contact
WHERE contact.published = 1
GROUP BY contact.user_id, contact.language) AS contact ON contact.user_id = a.created_by
LEFT JOIN j25_categories as parent ON parent.id = c.parent_id
LEFT JOIN j25_content_rating AS v ON a.id = v.content_id
LEFT OUTER JOIN (SELECT cat.id as id FROM j25_categories AS cat JOIN j25_categories AS parent ON cat.lft BETWEEN parent.lft AND parent.rgt WHERE parent.extension = 'com_content' AND parent.published != 1 GROUP BY cat.id ) AS badcats ON badcats.id = c.id
WHERE a.access IN (1,1) AND c.access IN (1,1) AND CASE WHEN badcats.id is null THEN a.state ELSE 0 END = 1 AND a.featured = 0 AND a.catid IN (181,89,173,174,49,128,124,175,129,133,121,176,135,180,177,178,179,90) AND (a.publish_up = '0000-00-00 00:00:00' OR a.publish_up <= '2013-11-26 12:04:24') AND (a.publish_down = '0000-00-00 00:00:00' OR a.publish_down >= '2013-11-26 12:04:24')
GROUP BY a.id, a.title, a.alias, a.title_alias, a.introtext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias, a.created, a.modified, a.modified_by, uam.name, a.publish_up, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, a.fulltext, a.state, a.publish_down, badcats.id, c.title, c.path, c.access, c.alias, uam.id, ua.name, ua.email, contact.id, parent.title, parent.id, parent.path, parent.alias, v.rating_sum, v.rating_count, c.published, c.lft, a.ordering, parent.lft, fp.ordering, c.id, a.images, a.urls
ORDER BY a.created DESC LIMIT 0, 12;
What can I do to speed it up? Would indexing some of these tables help?
Thank you.

Absolutely indexes help in queries. And each of what I consider your secondary lookup reference tables (categories, users, content rating, etc) should have an index at a MINIMUM on what your join condition is between the tables.
table index on
j25_content ( access, featured, catid, publish_up, publish_down, state, id, created_by, modified_by )
j25_content_frontpage ( content_id )
j25_categories ( id, parent_id )
ANOTHER index...
j25_categories ( extension, published, lft, rgt, id )
j25_users ( id )
j25_contact_details ( published, user_id, language, id )
j25_content_rating ( content_id )
I've set these indexes up to be "covering" indexes... meaning they should help the optimization of the query by having all the fields as part of the index so it does not have to go to the raw data pages to see if all the pieces qualify to return a record
TRY that first...
NEXT thing I would try is MySQL has a special keyword "STRAIGHT_JOIN" which tells the
engine to run the query in the order you have stated. You seem to have a good basis
of the tables as the primary and your lookup as secondary. The engine might be trying
to think for you and use one of the smaller tables to run the query.
select STRAIGHT_JOIN (rest of your query exactly as it is)

Related

SQL - Improving JOIN query (Taking long time to load)

I have below query, which I believe I have optimized as much as I possible could:
SELECT
c.forum_id as category_id,
c.forum_name as category_name,
t.forum_id as id,
t.forum_name as name,
t.forum_desc as description,
(SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
(SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
(SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
lp.topic_id as last_post_topic_id,
lp.topic_title as last_post_topic_title,
lp.post_time as last_post_time,
lp.username as last_post_username,
lp.avatar
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
SELECT
ft.topic_id,
ft.title as topic_title,
tmp.post_time,
u.username,
u.avatar,
fp.forum_id
FROM
forum_posts fp
join forum_topics ft on ft.topic_id = fp.topic_id
join users u on u.id = fp.userid
join (
select forum_id, max(`post_time`) `post_time`
from forum_posts fp
where fp.post_deleted = 0
group by forum_id
) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
order by category_id, t.forum_id
This is the stats for each forum:
forum_cats has 20 rows
forum_topics has 900 rows
forum_posts has 9000 rows
users has 18000 rows
I have added index on all the columns that is being selected in above query. Yet it still takes more than 2 seconds to execute this.
What am I missing here?
Won't topics_count, posts_count & last_post_count be the same for every row? Wouldn't it be more efficient to pull these values separately, rather than make the same 3 calculations for every row you pull?

MySQL / PDO - Select from other table (Join statement)

I have a PDO statement, that selects some data from some different tables. Although, I am unsure on how I can select data from yet another table:
SELECT
c.forum_id as category_id,
c.forum_name as category_name,
t.forum_id as id,
t.forum_name as name,
t.forum_desc as description,
(SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
(SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
(SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
lp.topic_id as last_post_topic_id,
lp.topic_title as last_post_topic_title,
lp.post_time as last_post_time,
lp.username as last_post_username
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
SELECT
ft.topic_id,
ft.title as topic_title,
tmp.post_time,
u.username,
fp.forum_id
FROM
forum_posts fp
join forum_topics ft on ft.topic_id = fp.topic_id
join users u on u.id = fp.userid
join (
select forum_id, max(`post_time`) `post_time`
from forum_posts fp
where fp.post_deleted = 0
group by forum_id
) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
order by category_id, t.forum_id
");
Now, I want to select the column avatar.users where username.users is = last_post_username (avatar column, from the users table).
I have absolute no idea on where to start. Should I put it something like this?
(SELECT avatar FROM users WHERE username=last_post_username)
That doesn't work though.
Any help is appreciated.
You already have "last_post_username" based on a join as "u.id = fp.userid". You just need to retrieve "lp.avatar"
Here is my answer :
SELECT
c.forum_id as category_id,
c.forum_name as category_name,
t.forum_id as id,
t.forum_name as name,
t.forum_desc as description,
(SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
(SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
(SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
lp.topic_id as last_post_topic_id,
lp.topic_title as last_post_topic_title,
lp.post_time as last_post_time,
lp.username as last_post_username,
lp.avatar
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
SELECT
ft.topic_id,
ft.title as topic_title,
tmp.post_time,
u.username,
u.avatar,
fp.forum_id
FROM
forum_posts fp
join forum_topics ft on ft.topic_id = fp.topic_id
join users u on u.id = fp.userid
join (
select forum_id, max(`post_time`) `post_time`
from forum_posts fp
where fp.post_deleted = 0
group by forum_id
) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
order by category_id, t.forum_id
");

Having problems writing mysql query joining 4 tables

I have a query (which partially works) looking like the following:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`,
`cms_dealer_inventory_media` AS `m`,
`cms_dealer_account` AS `a`,
`cms_dealer_setting` AS `s`
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.vehicle_id=i.vehicle_id
AND m.type='exterior'
AND a.user_id=i.user_id
AND s.user_id=i.user_id
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
The problem is, the cms_dealer_inventory_media may or may not contain images (bind by vehicle_id). I know the problem is with my WHERE statement in which I am specifically saying m.vehicle_id=i.vehicle_id AND m.type='exterior' but, it causes entries with no images to be ignore.
What I need is a query which makes the m.vehicle_id=i.vehicle_id run IF there are results to cms_dealer_inventory_media.
You should use left join
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i` left join
`cms_dealer_inventory_media` AS `m` on m.vehicle_id=i.vehicle_id
AND m.type='exterior' left join
`cms_dealer_account` AS `a` on a.inventory_status='1'
AND a.user_id=i.user_id AND a.country='DE' left join
`cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
If you change your query to use the more modern explicit joins, you could use left joins:
SELECT i.vehicle_id, i.user_id, i.make, i.model, i.year, i.state, i.price, i.class, i.fuel, i.mileage, i.mileage_type, i.featured, i.published, i.creation, i.status, m.vehicle_id, m.type, m.src, a.user_id, a.inventory_status, a.country, s.user_id, s.currency_iso, s.currency_code
FROM `cms_dealer_inventory` AS `i`
LEFT JOIN `cms_dealer_inventory_media` AS `m` ON m.vehicle_id=i.vehicle_id
LEFT JOIN `cms_dealer_account` AS `a` ON a.user_id=i.user_id
LEFT JOIN `cms_dealer_setting` AS `s` ON s.user_id=i.user_id
WHERE i.make='chevrolet'
AND i.model='camaro'
AND i.year='2014'
AND (i.mileage <= 200000 )
AND i.published='1'
AND a.inventory_status='1'
AND m.type='exterior'
AND a.country='DE'
GROUP BY i.vehicle_id
ORDER BY i.featured DESC, i.price ASC, i.state DESC, i.make ASC
you will have to use the join properly
in your case you need all the records from cms_dealer_inventory
so join will be cms_dealer_inventory left outer cms_dealer_inventory_media

PHP - Join statement duplicates records

I have quite a large query, which basically shows the different forums I have stored in my database, to my users:
$stmt = $dbh->prepare("
SELECT
c.forum_id as category_id,
c.forum_name as category_name,
t.forum_id as id,
t.forum_name as name,
t.forum_desc as description,
(SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
(SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
(SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
lp.topic_id as last_post_topic_id,
lp.topic_title as last_post_topic_title,
lp.post_time as last_post_time,
lp.username as last_post_username
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
SELECT
ft.topic_id,
ft.title as topic_title,
tmp.post_time,
u.username,
fp.forum_id
FROM
forum_posts fp
join forum_topics ft on ft.topic_id = fp.topic_id
join users u on u.id = fp.userid
join (
select forum_id, max(`post_time`) `post_time`
from forum_posts fp
where fp.post_deleted = 0
group by forum_id
) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
order by category_id, t.forum_id
");
$stmt->execute();
I then do a while loop to show all the records:
while (($row = $stmt->fetch())) {
echo $row['name'];
}
The problem is, that during the while loop, I get fine results sometimes!
It should look like this:
forum1
forum2
forum3
forum4
forum5
forum6
etc.
But sometimes I get results like this:
forum1
forum1
forum1
forum1
forum2
forum3
forum4
forum5
forum6
Some of the rows (it's quite random which row) are being 'duplicated'.
Can someone help me shed light on this?
Try grouping by adding GROUP BY t.forum_id:
SELECT
c.forum_id as category_id,
c.forum_name as category_name,
t.forum_id as id,
t.forum_name as name,
t.forum_desc as description,
(SELECT COUNT(*) FROM forum_topics WHERE forum_id=t.forum_id AND topic_deleted=0) as topics_count,
(SELECT COUNT(*) FROM forum_posts WHERE forum_id=t.forum_id AND post_deleted=0) as posts_count,
(SELECT COUNT(*) FROM forum_posts WHERE topic_id=lp.topic_id AND post_deleted=0) as last_post_count,
lp.topic_id as last_post_topic_id,
lp.topic_title as last_post_topic_title,
lp.post_time as last_post_time,
lp.username as last_post_username
FROM forum_cats as t
JOIN forum_cats as c on c.forum_id = t.forum_type_id
left join (
SELECT
ft.topic_id,
ft.title as topic_title,
tmp.post_time,
u.username,
fp.forum_id
FROM
forum_posts fp
join forum_topics ft on ft.topic_id = fp.topic_id
join users u on u.id = fp.userid
join (
select forum_id, max(`post_time`) `post_time`
from forum_posts fp
where fp.post_deleted = 0
group by forum_id
) as tmp on (fp.forum_id = tmp.forum_id and fp.post_time = tmp.post_time)
where post_deleted = 0 and ft.topic_deleted = 0
) as lp on lp.forum_id = t.forum_id
where t.forum_active = 1 and c.forum_active = 1
GROUP BY t.forum_id
order by category_id, t.forum_id

Ridiculously slow MySQL Queries in Joomla 3.x

Before I go any further, let me just say, I've already done everything that's recommended when you google "slow joomla" or "optimize joomla". That is, my site is GZipped, all of my css and js are optimized and minified, I'm not running any unnecessary components, plugins, or modules (hardly any, in fact), my images are optimized, caching is turned on (both page and Progressive) and I'm on supah-fast cloud hosting from Rackspace, with my SQL Database on a separate Rackspace server.
All of that, and I'm still getting load times upwards of 10-12 seconds, sometimes as much as 14-15.
From Joomla debug:
Application 0.000 seconds (+0.000); 0.75 MB (+0.755) - afterLoad
Application 0.027 seconds (+0.027); 2.25 MB (+1.491) - afterInitialise
Application 0.040 seconds (+0.013); 3.26 MB (+1.010) - afterRoute
Application 11.986 seconds (+11.947); 5.09 MB (+1.833) - afterDispatch
Application 12.000 seconds (+0.014); 5.63 MB (+0.539) - beforeRenderModule mod_chronoforms (Tip Line)
Application 12.006 seconds (+0.005); 5.85 MB (+0.225) - afterRenderModule mod_chronoforms (Tip Line)
Application 12.008 seconds (+0.002); 5.86 MB (+0.006) - beforeRenderModule mod_custom_advanced (Sponsors)
Application 12.009 seconds (+0.002); 5.88 MB (+0.019) - afterRenderModule mod_custom_advanced (Sponsors)
Application 12.010 seconds (+0.001); 5.87 MB (-0.006) - beforeRenderModule mod_flexi_customcode (Popular Now)
Application 12.012 seconds (+0.002); 5.89 MB (+0.018) - afterRenderModule mod_flexi_customcode (Popular Now)
Application 12.012 seconds (+0.001); 5.84 MB (-0.046) - beforeRenderModule mod_articles_category (Featured Articles)
Application 12.033 seconds (+0.021); 5.97 MB (+0.127) - afterRenderModule mod_articles_category (Featured Articles)
Application 12.033 seconds (+0.000); 5.96 MB (-0.014) - beforeRenderModule mod_search (Search)
Application 12.036 seconds (+0.002); 5.98 MB (+0.022) - afterRenderModule mod_search (Search)
Application 12.036 seconds (+0.001); 5.93 MB (-0.050) - beforeRenderModule mod_acymailing (AcyMailing Module)
Application 12.044 seconds (+0.007); 6.44 MB (+0.507) - afterRenderModule mod_acymailing (AcyMailing Module)
Application 12.157 seconds (+0.114); 6.72 MB (+0.289) - afterRender
the (+11.947) for afterDispatch is what tipped me off that it was probably an issue with the MySQL queries, so I started running some of the long (long, LONG) ones through PHPMyAdmin.
I found that queries such as these (the first of which loads 8 articles for the category-blog view -- as far as I understand, the second does the same search, minus the LIMIT, to allow for pagination) take over 2 or 3 second EACH to complete and there are 40-some-odd queries (though the vast majority are nowhere near as unwieldy) every time a page loads:
SELECT a.id, a.title, a.alias, a.introtext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias,
CASE WHEN a.modified = '0000-00-00 00:00:00' THEN a.created ELSE a.modified END as modified, a.modified_by, uam.name as modified_by_name,
CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END as publish_up,a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, LENGTH(a.fulltext) AS readmore,
CASE WHEN badcats.id is not null THEN 0 ELSE a.state END AS state,c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias,
CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author,ua.email AS author_email,contact.id as contactid,parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias,ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count,c.published,
CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published
FROM mydatabase_content AS a
LEFT JOIN mydatabase_content_frontpage AS fp
ON fp.content_id = a.id
LEFT JOIN mydatabase_categories AS c
ON c.id = a.catid
LEFT JOIN mydatabase_users AS ua
ON ua.id = a.created_by
LEFT JOIN mydatabase_users AS uam
ON uam.id = a.modified_by
LEFT JOIN ( SELECT contact.user_id, MAX(contact.id) AS id, contact.language
FROM mydatabase_contact_details AS contact
WHERE contact.published = 1
GROUP BY contact.user_id, contact.language) AS contact
ON contact.user_id = a.created_by
LEFT JOIN mydatabase_categories as parent
ON parent.id = c.parent_id
LEFT JOIN mydatabase_content_rating AS v
ON a.id = v.content_id
LEFT
OUTER JOIN (SELECT cat.id as id
FROM mydatabase_categories AS cat JOIN mydatabase_categories AS parent
ON cat.lft BETWEEN parent.lft
AND parent.rgt
WHERE parent.extension = 'com_content'
AND parent.published != 1
GROUP BY cat.id ) AS badcats
ON badcats.id = c.id
WHERE a.access IN (1,1,5)
AND c.access IN (1,1,5)
AND
CASE WHEN badcats.id is null THEN a.state ELSE 0 END = 1
AND (a.catid = 164 OR a.catid IN ( SELECT sub.id
FROM mydatabase_categories as sub
INNER JOIN mydatabase_categories as this
ON sub.lft > this.lft
AND sub.rgt < this.rgt
WHERE this.id = 164))
AND (a.publish_up = '0000-00-00 00:00:00' OR a.publish_up <= '2013-08-07 07:00:01')
AND (a.publish_down = '0000-00-00 00:00:00' OR a.publish_down >= '2013-08-07 07:00:01')
GROUP BY a.id, a.title, a.alias, a.introtext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias, a.created, a.modified, a.modified_by, uam.name, a.publish_up, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, a.fulltext, a.state, a.publish_down, badcats.id, c.title, c.path, c.access, c.alias, uam.id, ua.name, ua.email, contact.id, parent.title, parent.id, parent.path, parent.alias, v.rating_sum, v.rating_count, c.published, c.lft, a.ordering, parent.lft, fp.ordering, c.id, a.images, a.urls
ORDER BY
CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END DESC , a.created
LIMIT 0, 7
---
SELECT a.id, a.title, a.alias, a.introtext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias,
CASE WHEN a.modified = '0000-00-00 00:00:00' THEN a.created ELSE a.modified END as modified, a.modified_by, uam.name as modified_by_name,
CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END as publish_up,a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, LENGTH(a.fulltext) AS readmore,
CASE WHEN badcats.id is not null THEN 0 ELSE a.state END AS state,c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias,
CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author,ua.email AS author_email,contact.id as contactid,parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias,ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count,c.published,
CASE WHEN badcats.id is null THEN c.published ELSE 0 END AS parents_published
FROM mydatabase_content AS a
LEFT JOIN mydatabase_content_frontpage AS fp
ON fp.content_id = a.id
LEFT JOIN mydatabase_categories AS c
ON c.id = a.catid
LEFT JOIN mydatabase_users AS ua
ON ua.id = a.created_by
LEFT JOIN mydatabase_users AS uam
ON uam.id = a.modified_by
LEFT JOIN ( SELECT contact.user_id, MAX(contact.id) AS id, contact.language
FROM mydatabase_contact_details AS contact
WHERE contact.published = 1
GROUP BY contact.user_id, contact.language) AS contact
ON contact.user_id = a.created_by
LEFT JOIN mydatabase_categories as parent
ON parent.id = c.parent_id
LEFT JOIN mydatabase_content_rating AS v
ON a.id = v.content_id
LEFT
OUTER JOIN (SELECT cat.id as id
FROM mydatabase_categories AS cat JOIN mydatabase_categories AS parent
ON cat.lft BETWEEN parent.lft
AND parent.rgt
WHERE parent.extension = 'com_content'
AND parent.published != 1
GROUP BY cat.id ) AS badcats
ON badcats.id = c.id
WHERE a.access IN (1,1,5)
AND c.access IN (1,1,5)
AND
CASE WHEN badcats.id is null THEN a.state ELSE 0 END = 1
AND (a.catid = 164 OR a.catid IN ( SELECT sub.id
FROM mydatabase_categories as sub
INNER JOIN mydatabase_categories as this
ON sub.lft > this.lft
AND sub.rgt < this.rgt
WHERE this.id = 164))
AND (a.publish_up = '0000-00-00 00:00:00' OR a.publish_up <= '2013-08-07 07:00:01')
AND (a.publish_down = '0000-00-00 00:00:00' OR a.publish_down >= '2013-08-07 07:00:01')
GROUP BY a.id, a.title, a.alias, a.introtext, a.checked_out, a.checked_out_time, a.catid, a.created, a.created_by, a.created_by_alias, a.created, a.modified, a.modified_by, uam.name, a.publish_up, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.xreference, a.featured, a.fulltext, a.state, a.publish_down, badcats.id, c.title, c.path, c.access, c.alias, uam.id, ua.name, ua.email, contact.id, parent.title, parent.id, parent.path, parent.alias, v.rating_sum, v.rating_count, c.published, c.lft, a.ordering, parent.lft, fp.ordering, c.id, a.images, a.urls
ORDER BY
CASE WHEN a.publish_up = '0000-00-00 00:00:00' THEN a.created ELSE a.publish_up END DESC , a.created
EDIT
Here's the EXPLAIN for the first query:
And for the second:
My _content table is a little over 14,000 rows, which I know isn't really all that much in the grand scheme of things.
/EDIT
Has anyone found a good way to optimize this? I'm not opposed to hacking the core (I know they say not to, but what's the point of an open source project if you can't get in and fiddle with it?) if that's what it takes.
EDIT 2 - SOLVED (sort of).
So, I found this guy who seems to be going down the right path, so I said to hell with it, and tried it.
In components/com_content/models/articles.php, I replaced line 431
$query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
with
$query->where('(a.publish_up >= DATE_SUB(NOW(), INTERVAL 1 YEAR))');
I know this won't work for everyone, as it probably breaks pagination, but it seems to be working for me so far (my template uses a js infinite scroll solution instead of pagination). I figure if anyone is looking for an article over a year old, they can use the Search function.
Those two queries now each take less that .04 seconds to complete, and the afterDispatch time from Joomla Debug is down to 1.469 seconds -- not optimal, but a number I can live with and continue to whittle down.
I know this solution is pretty hacky, and probably won't work for anyone else, so I'd love to hear more ideas about improving/optimizing the Joomla core and the Joomla stock queries.
Thanks SO!
/EDIT 2
As I have posted here already: JOOMLA site too slow
I uncommented the
bind-address="127.0.0.1"
setting in the MySQL configuration file (my.ini).
This brought an increase of execution speed to my local Joomla installation on Windows 8.1.
There is an issue with the join on the contact table and the resulting group_by.
This is fixed in master with https://github.com/joomla/joomla-cms/pull/1542 and I think it should already be included in the current release.
Which version of Joomla are you using?
i had a problem on windwos hosting php+mysql. set host to ip address.
host 127.0.0.1

Categories