B
B
BonBon Slick2017-04-17 15:20:11
MySQL
BonBon Slick, 2017-04-17 15:20:11

How to optimize a query for 700,000+ records?

mysql, phpmyadmin, laravel.

$articles = DB::table('articles')->select('articles.*','folders.path','folders.title as parent_title')
        ->join('folders','folders.id','=','articles.parent_folder_id')
        ->orderBy('articles.sticked', 'DESC')
        ->orderby('published_at', 'DESC')

         ->limit(20)
         ->get();
// это весь запрос

And this is already redone, it was even bigger. Indexes in the database are added on sticked, published_at in the articles table.
The folder title is needed to form the URL of the article. I think I can add a column in the articles table with a ready-made URL, so you don't have to join it every time you select it. Or split into several small subqueries.
The number of articles is hundreds of thousands, there are also quite a few folders.
542000cf6f034af98106cdf5d56a8771.png
The SQL itself of the picture above:
EXPLAIN 
select `slc_articles`.*, `slc_folders`.`path`, `slc_folders`.`title`as `parent_title` from `slc_articles` 
inner join `slc_folders` on `slc_folders`.`id` = `slc_articles`.`parent_folder_id` 
order by `slc_articles`.`sticked` desc, `published_at` desc 
limit 11 
offset 0

This request is processed in 2.5-4.5 seconds, how can I optimize to 0.5-1.5?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
Anton Anton, 2017-04-17
@BonBonSlick

the composite index with the necessary sorting is necessary. Well, in general, the stickiness index is a complicated thing. it's better to make two dates (one to display and one to sort/display sticky on top). Well, or store the sticky id in a separate place and get a list by id + the rest - from those sorted by date with the exception of sticky id. In any case, experiments are needed.
Well, at any cost, remove join from the query, perhaps at the cost of two queries or wrapping the main select in a subquery ( select ... from (select ... order by ... limit 10 ) as subquery inner join ... );

A
Alexander Drozdov, 2017-04-17
@bagzon

Well, there are 2 variants, as for me
1) Pull out all folders with one request, make its ID a key, cache it, and then go through everything calmly during the cycle. Also, do not forget about updating the cache when updating or inserting new data.
Sometimes logic works faster in PHP than in pure SQL
2) There is also a variant to make another table where you combine all the data of two tables, so to speak, simplify. Also you will make indexes necessary to you. Well, the same problem with updating the data, when updating / inserting, update your new table.
See what else you can cache in the app.

M
mamayama, 2017-04-17
@mamayama

And indexes on Join?

E
Evgeny Bukharev, 2017-04-17
@evgenybuckharev

Here index try to add articles.parent_folder_id

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question