0

I have function in CodeIgniter to retrieve latest posts from 2 tables:

public function get_latest_comments($amount)
{
  $query = $this->db->query('
    SELECT *, FROM_UNIXTIME(date) AS timestamp
    FROM comments
    ORDER BY timestamp DESC
    LIMIT 5
  ');

  if ($query->num_rows() > 0) {
    $result = $query->result_array();

    for ($i = 0; $i < sizeof( $result ); $i++) {
      $result[$i]['author_info'] = $this->comments_model->get_comment_author( $result[$i]['id'] );
      $result[$i]['date'] = mdate( "%M %m, %Y", $result[$i]['date'] );

      if ($result[$i]['section'] === 'blog') $loc = 'blog_posts';
      if ($result[$i]['section'] === 'core') $loc = 'public_posts';

      $this->db->select( 'title, slug' );
      $query = $this->db->get_where( $loc, array('id' => $result[$i]['location']) );

      $result[$i]['post_title'] = $query->row( 'title' );
      $result[$i]['url'] = base_url() . $result[$i]['section'] . '/view/' . $query->row( 'slug' ) . '/';
    }
    return $result;
  }
  return false;
}

The problem is that it runs too slow. My page sometimes loads 7-8 seconds. I suspect this query running 2 times + similar query gathering latest comments slows down my page.

I have a bad feeling about queries inside the loop. How can I avoid that?

The structure of my table is:

users (id, username, mail ...
user_info ( user_id, name, surname
public_posts ( id, slug, text, author(user id) ...
blog_posts ( id, slug, text ...
comments ( id, text, author, location(post_id_, section(post_table) ...
4
  • How about getting the comment other by joining it in the query instead of querying for each row? Commented Apr 3, 2013 at 9:14
  • I'm not sql guru, i would be grateful if you showed me an example Commented Apr 3, 2013 at 9:29
  • The query above really shouldn't be that slow even with the embedded query. The most common reason for slow queries is no indexes defined beyond a primary. For example in the above tables you'd want to set an index on user_id anywhere it appears and post_id as well. Just make sure you set them as indexes and not primary (unless it is for the right table) or unique. I think you'll find doing that makes a huge difference. You can do this on the structure page for each table in phpmyadmin Commented Apr 3, 2013 at 10:12
  • What does the profiler shows? Try adding a $this->output->enable_profiler(true); into your controller and check what queries ran and with what time. Adding explain before the individual queries should tell if you are doing a full table scans or not. Commented Apr 3, 2013 at 11:07

1 Answer 1

3

Check by expalining your Query , Go to the mysql command line and type

EXPLAIN SELECT *, FROM_UNIXTIME(date) AS timestamp FROM comments ORDER BY timestamp DESC LIMIT 5

Explain will tell you everything about the query, On its bases you can decide for the indexing also. Make a practice to expalin every select query before using it in the code.

Plus you can also do profiling when ever you think your code is taking time. In codeigniter Profiler class is available, please go through the below link.

https://www.codeigniter.com/userguide3/general/profiling.html

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.