Xwab
Форумыnavigate_nextПрограммирование на PHP

Помогите оптимизировать SQL запрос
Сообщения
Smarik

База MySQL, есть рабочий запрос

SELECT id,
    (
        SELECT count( frm.id )
        FROM forum frm
        WHERE frm.user_id = pls.id
    ) AS countForum,
    (
        SELECT count( cmt.id )
        FROM comments cmt
        WHERE cmt.player_id = pls.id
    ) AS countComments
FROM players pls

Запрос работает правильно, все хорошо, кроме одного! Сайт вырос и теперь этот запрос работает от 52 до 54 секунд.
Решил его оптимизировать, ибо он начал ложить мой сервак в глухую, сделал так

SELECT id,
    (
        SELECT count( frm.id )
        FROM forum frm
        inner join players pls2 ON frm.user_id = pls2.id AND pls2.id = pls.id
    ) AS countForum,
    (
        SELECT count( cmt.id )
        FROM comments cmt
        inner join players pls3 ON cmt.player_id = pls3.id AND pls3.id = pls.id
    ) AS countComments
FROM players pls

по идее это должно спасти ситуацию и снизить время работы с 54 до 0,5 сек (примерно), т.к. в этом случае я не тегаю все сообщения форума, а только сообщения форума от этого юзера, но мускул мне говорит что pls.id в подзапросах недоступен, хотя в первом варианте через where он доступен...

18 Окт 2012, 11:35
Okula

Добавь индексы к полям, тогда запросы будут работать быстрее.
SELECT pls.`id`,
     (
         SELECT count( frm.`id` )
         FROM `forum` AS frm
         INNER JOIN `players` AS pls2 ON frm.`user_id` = pls2.`id` AND pls2.`id` = pls.`id`
     ) AS countForum,
     (
         SELECT count( cmt.`id` )
         FROM `comments` AS cmt
         INNER JOIN `players` AS pls3 ON cmt.`player_id` = pls3.`id` AND pls3.`id` = pls.`id`
     ) AS countComments
 FROM `players` AS pls


__________
посл.ред. 18 Окт 2012, 12:08; всего 1 раз 18 Окт 2012, 12:00
Smarik

#1054 - Unknown column 'pls.id' in 'on clause'

18 Окт 2012, 12:03
Okula

В самом начале добавь алиас имени таблицы к полю id:
SELECT pls.`id`,

18 Окт 2012, 12:06
Smarik

Тоже самое

18 Окт 2012, 12:09
Okula

Выложи структуру базы данных, иначе гадать можно сколько угодно.

18 Окт 2012, 12:11
Smarik

Ну для теста достаточно по 1 полю
таблица players
id
табилца forum
id, user_id
таблица comments
id, player_id
user_id и player_id это внешние ключи на players.id, они называются по разному, потому что я наверно был упоротый когда делал бд и таблицы в очень разное время создавались ^^

18 Окт 2012, 12:17
Okula

Можешь создать таблицы (с полями которые используются) и выложить тут дамп? Нет особого желания таблицы делать

18 Окт 2012, 12:23
Smarik


CREATE TABLE IF NOT EXISTS `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `player_id` int(11) NOT NULL,
  `text` varchar(5000) NOT NULL,
  `date` int(11) NOT NULL DEFAULT '1344211421',
  `type` int(11) NOT NULL,
  `type_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=6248 ;

CREATE TABLE IF NOT EXISTS `forum` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `desc` varchar(5000) DEFAULT NULL,
  `idForum` int(11) NOT NULL,
  `idTheme` int(11) NOT NULL,
  `date` int(11) NOT NULL,
  `type` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=36814 ;

CREATE TABLE IF NOT EXISTS `players` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `login` varchar(18) NOT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `login` (`login`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=2680 ;

добавлено спустя 15 часов 32 минуты:
Ну что, вариантов нет?

19 Окт 2012, 4:12
m_kobernyk

1. COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause;
2. LEFT JOIN лучше, чем подзапросы;
3. (без претензий на истинность) попробуй сменить WHERE на HAVING. Доки по этому поводу не читал, но возможно поможет

ЗЫ. Юзверг, зачем тебе INNER JOIN при выборке COUNT()???

ЗЗЫ. Да, и индексы в БД проставь

19 Окт 2012, 8:39
Ответить на тему