Question

I have a table in MySQL that contains a lot of articles.
Here is the table structure:

CREATE TABLE articles (
  id char(32) default NULL,
  title char(192) default NULL,
  time int(10) unsigned default NULL,
  image char(255) default NULL,
  views mediumint(8) unsigned default '0',
  category char(128) default NULL
);

Insert example:

INSERT INTO articles VALUES ('0123456789abcdef0123456789abcdef','Article Title',1204149600,'http://www.example.com/image.jpg',1234,'sports');

I have over 50000 rows in this table.

Everything is working well!

Now, I decided to create TAGS for my articles.
I made a php script that scans all articles and creates a mysql table.
Here is the table structure for tags:

CREATE TABLE tags (
  id char(32) default NULL,
  tag char(192) default NULL
);

Insert example:

INSERT INTO tags VALUES ('0123456789abcdef0123456789abcdef','BALL');

I have over 100000 rows in this table.
tags.id is the id of the article.
One article can have many tags and one tag can be assigned to many articles.

When I want to get all tags for an article, I'm doing this:

SELECT tag FROM tags WHERE id = '0123456789abcdef0123456789abcdef';

This is working OK!


THE PROBLEM:
I'm trying to get a list of articles of a specific tag.

I tried the following queries, but it takes over 30 seconds to execute and the php times out and a "500 Internal Server Error" is returned by the server.
Here are the queries I tried:

SELECT * FROM `articles`,`tags` WHERE `articles`.`id` = `tags`.`id` AND `tags`.`tag` = 'BALL' ORDER BY `time` DESC LIMIT 10;
SELECT * FROM `articles` JOIN `tags` ON `articles`.`id` = `tags`.`id` WHERE `tags`.`tag` = 'BALL' ORDER BY `time` DESC LIMIT 10;
SELECT * FROM `articles` WHERE `id` IN (SELECT `id` FROM `tags` WHERE `tag` = 'BALL') ORDER BY `time` DESC LIMIT 10;




I run this:

explain SELECT * FROM articles JOIN tags ON articles.id = tags.id WHERE tags.tag = 'BALL' ORDER BY time DESC LIMIT 10;

and I get this result:


  array (
    0 =>
    array (
      'id' => '1',
      'select_type' => 'SIMPLE',
      'table' => 'articles',
      'type' => 'ALL',
      'possible_keys' => NULL,
      'key' => NULL,
      'key_len' => NULL,
      'ref' => NULL,
      'rows' => '54019',
      'Extra' => 'Using temporary; Using filesort',
    ),
    1 =>
    array (
      'id' => '1',
      'select_type' => 'SIMPLE',
      'table' => 'tags',
      'type' => 'ALL',
      'possible_keys' => NULL,
      'key' => NULL,
      'key_len' => NULL,
      'ref' => NULL,
      'rows' => '119149',
      'Extra' => 'Using where; Using join buffer',
    ),
  )
Was it helpful?

Solution

It looks like you have indexing problem. Please create index for id in 'Tag' table and id in 'articles ' table. To create index refer below link: http://dev.mysql.com/doc/refman/5.0/en/create-index.html

OTHER TIPS

You have no index on your tables that would allow MySQL to lookup you requested data, so it has to walk through every combination.

  1. (style) Give the tags table its own id and rename id to article_id

    ALTER TABLE tags change id article_id char(32), add column id int(11) not null auto_increment primary key;

  2. Give table tags an index on tag

    ALTER TABLE tags ADD INDEX(tags, article_id);

  3. Give table articles an index on id. If still possible, give it a UNIQUE INDEX.

    ALTER TABLE articles ADD INDEX(id);

If your table will grow, I would add a numeric internal column also:

ALTER TABLE articles ADD COLUMN tech_id int(11) not null primary key auto_increment;

You can then change referencing the 32-char-string in table tags to the int tech_id, if the system is getting slow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top