简体   繁体   中英

Mysql query is too slow when order by datetime

I have a table with about 10k rows. I run below sql but it's take too much time (~4 seconds):

SELECT
        ID, post_date, post_title, post_name, pc.post_view,
        t.name AS post_category,
        pm2.meta_value AS post_image
    FROM wp_posts p
        INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
        INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy='category'
        INNER JOIN wp_terms t ON tt.term_id = t.term_id AND (t.name='My Posts' OR t.name='HOT posts')
        LEFT JOIN post_counter pc ON p.ID = pc.post_id
        LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID AND pm.meta_key = '_thumbnail_id'
        LEFT JOIN wp_postmeta pm2 ON pm.meta_value = pm2.post_id AND pm2.meta_key = '_wp_attached_file'
    WHERE p.post_status = 'publish' AND p.post_type = 'post'
    ORDER BY FIELD(t.name, 'HOT posts', 'My Posts'), post_date DESC
    LIMIT 14

If I remove "order by post_date", everything fine. It's take only 0.05 second to run.

I added some indexes with CREATE INDEX and ADD INDEX (I don't know what's difference between them):

CREATE INDEX ix_type_date ON wp_posts (post_type, post_date)

ALTER TABLE wp_posts ADD INDEX ix_status_type_date (post_status,post_type,post_date)

Then use these indexes with USE INDEX and FORCE INDEX (I also don't know what's difference between them):

    ...FROM wp_posts p USE INDEX (ix_type_date)...

OR

    ...FROM wp_posts p FORCE INDEX (ix_status_type_date)...

I still get my records, but loading time increased to 7-8 seconds.

Really need your helps! Thanks in advanced!

EDIT:

Table's structure

ID  bigint(20)  No           
post_author bigint(20)  No  0        
post_date   datetime    No  0000-00-00 00:00:00          
post_date_gmt   datetime    No  0000-00-00 00:00:00          
post_content    longtext    No           
post_title  text    No           
post_excerpt    text    No           
post_status varchar(20) No  publish          
comment_status  varchar(20) No  open         
ping_status varchar(20) No  open         
post_password   varchar(255)    No           
post_name   varchar(200)    No           
to_ping text    No           
pinged  text    No           
post_modified   datetime    No  0000-00-00 00:00:00          
post_modified_gmt   datetime    No  0000-00-00 00:00:00          
post_content_filtered   longtext    No           
post_parent bigint(20)  No  0        
guid    varchar(255)    No           
menu_order  int(11) No  0        
post_type   varchar(20) No  post         
post_mime_type  varchar(100)    No           
comment_count   bigint(20)  No  0 

You want "Hot posts" first, then "my posts"? And there are likely to be fewer than 14 Hotties, and there are lots of "my posts"?

One clumsy solution is to

( SELECT ... name='HOT posts' ORDER BY post_date DESC  LIMIT 14 )
UNION ALL
( SELECT ... name='My Posts'  ORDER BY post_date DESC  LIMIT 14 )
ORDER BY field(...), post_date DESC  LIMIT 14

Note that there is some chance of quickly finding the latest 14 of each category, then quickly rearranging the 28 to get the desired 14.

For many-to-many tables, see here for how to improve their performance. (The default WP is rather inefficient.)

If you need to discuss further, please provide EXPLAIN SELECT ... and SHOW CREATE TABLE .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM