Консультация № 187493
29.06.2013, 12:05
99.51 руб.
0 1 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:

Как в моем случае лучше оптимизировать структуру таблиц запрос.

Есть табличка пользователей:
CREATE TABLE IF NOT EXISTS `users` (
`uid` int(11) NOT NULL,
`adddate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gold` int(11) NOT NULL,
`pass` varchar(15) NOT NULL,
`email` varchar(60) NOT NULL,
`login` varchar(32) NOT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Есть табличка страниц

CREATE TABLE IF NOT EXISTS `pages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`adddate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`user` int(11) NOT NULL,
`name` varchar(70) CHARACTER SET utf8 NOT NULL,
`link` varchar(256) CHARACTER SET utf8 NOT NULL,
`gold` int(11) NOT NULL,
`click` int(11) NOT NULL,
`pass` int(11) NOT NULL,
`prs` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`),
KEY `user` (`user`)
KEY `prs` (`prs`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

И есть табличка посещений этих страниц

CREATE TABLE IF NOT EXISTS `clik` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL, // Это id пользователя
`postid` int(11) NOT NULL, // Это id странички
PRIMARY KEY (`id`),
KEY `postid` (`postid`),
KEY `uid` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Пользователь выполняет запрос

SELECT pages.id,prs,link,name
FROM pages
LEFT OUTER JOIN clik ON ((pages.id = clik.postid)
and (clik.uid ='.$_SESSION['uid'].'))
WHERE clik.id is null
and gold >= prs*'.rand(1,5).' // здесь берется запас, что бы при большом количестве пользователей не было страничек без gold
and pass < 10
ORDER BY prs DESC,ID DESC
LIMIT 0 , 15

Соответственно получает список страниц которые еще не посещал.
Кликает на страничку - переходит не нее, выполняет действие.
Далее происходит проверка -
1. В табличке clik проверяется что такой записи нет
2. Проверяется действие совершенное пользователе на странице
3. Если действие совершено - с записи странички списывается gold(монеты) в размер prs(цена) и добавляется пользователю
если действие не выполнено - gold не добавляется
В табличку clik добавляется запись с id пользователя id странички , что бы при следующем селекте этой записи пользователю не выдавалось.
Если пользователь игнорирует страничку то ей добавляется значение pass. После 10 таких игноров страничка исключается(битая ссылка)


Сейчас сравнительно долго выполняется оператор селект. Вопрос - как уменьшить скорость его выполнения?
Добавить составной индекс из gold,pass? Но на сколько это увеличит производительность если gold постоянно меняется?

Обсуждение

Неизвестный
02.07.2013, 10:30
общий
это ответ
Здравствуйте, Посетитель - 397311!

По структуре тут предложить нечего: куда уж более оптимизировать.
Можно попробовать проиндексировать поле gold.
Индексировать pass имеет смысл только в том случае, если "битых" ссылок больше, чем не "битых".
Более того, в этом случае можно попробовать добавить поле isgood, которое будет иметь значение 1 для хороших ссылок и null для плохих,
проиндексировать его и выборку делать по этому полю.
Попробуйте поиграться с конструкциями NOT IN и NOT EXISTS как альтернативу LEFT JOIN/NOT NULL - может быть в этом конкретном случае будет выигрыш.

Хорошо бы увидеть план запроса, чтобы понять, в каком месте происходит задержка.

Форма ответа