Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не получается придумать индекс для таблицы, 100% нагрузка из-за просмотра всей таб. 
:(
    Опции темы
shevak
Дата 14.12.2010, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Всем доброе время суток.

Разработал сайт для одного интернет-аукциона. Все было неплохо, пока не начало расти количество пользователей (как всегда). В итоге сейчас дошло до того момента, что в пиковый момент под закрытие аукциона все начинают делать ставки и при 300 он-лайн пользователях идет 100% нагрузки на проц. Сервер отдельный для БД, мощный. 2 проца по 4 ядра, 12 Гб оперативки, RAID ...

В начале грешил на конфиг мускула, подправил - не помогло. Пользуюсь советами от mysqltuner - но не помогает. Дальше пошел к запросам на БД. большая часть запросов связана с таблицей ставок

Код

CREATE TABLE IF NOT EXISTS `rates` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `user_id` int(10) unsigned NOT NULL,
  `auction_id` int(11) NOT NULL,
  `sum` double default NULL,
  `status` int(10) unsigned NOT NULL,
  `place` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `user_id` (`user_id`),
  KEY `auction_id` (`auction_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=1272073 ;


В пиковый момент идет примерно 7 ставок в секунду, т.е. 7 Insertов в таблицу и порядка 60 чтений из нее. Сервер должен бы с таким справиться, но увы (((. 

Самый основной запрос - это получение таблицы ставок
Код

SELECT r.*, u.id as u_id, u.city, u.nikname 
FROM rates as r 
LEFT JOIN users as u ON u.id=r.user_id 
WHERE r.auction_id=439 
ORDER BY status,sum DESC,r.id LIMIT 0,25

Оптимизировать его никак не получается. Сортировка в таком порядке обязательна. А сложный индекс какой только не пробовал - не помогает.

Так же частый запрос пользователя на наличие ставки
Код

SELECT id FROM rates WHERE 1 AND auction_id='439' AND sum='72.62' AND status='1' 


На данный момент я решил делать для каждого аукциона отдельную таблицу ставок. Это уберет выбор по аукциону и индекс auction_id. И появится смысл сделать индекс по полю sum. Тесты показали что и запись и чтение вырастут примерно в 2 раза. Но все-равно останется запрос 
Код

SELECT r.*, u.id as u_id, u.city, u.nikname 
FROM rates as r 
LEFT JOIN users as u ON u.id=r.user_id 
ORDER BY status,sum DESC,r.id LIMIT 0,25

КОторый будет просматривать всю таблицу.

Вопрос:
1. Можно ли сделать индекс по полю status и sum, но только чтоб он сортировался именно status, sum DESC иначе от него не будет смысла.
2. Для хранения истории ставок я после закрытия аукционов перекидываю их в таблицу rates_close. Но если делать таблицу на каждый аукцион - то потом могут пересектись ай-дишники. Как в  этом случае лучше поступить. Выделять для каждой таблицы к примеру по 100 000 индексов? пока хватит, но если вдруг не хватит - все полетит?

Проблема очень для меня важная, буду очень признателен за любой совет, Спасибо!
PM MAIL   Вверх
triclosan
Дата 14.12.2010, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 18.8.2006

Репутация: 1
Всего: 12



Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
т.е. 7 Insertов в таблицу 

как вариант попробовать innodb, в целом она медленнее чем MyISAM, но при редактировании лок на уровне строк а не целой таблицы.



Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
sum='72.62'

хороший тон - для double  без кавычек.


Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
`status` int(10) unsigned NOT NULL,

если status это флаги, значений которых несколько, а не 2^32-1, то можно заюзать enum.



Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
На данный момент я решил делать для каждого аукциона отдельную таблицу ставок.

поясните, будете для каждого auction_id - create table выполнять? Это пагубно и не реляционно.


Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
Можно ли сделать индекс по полю status и sum

имхо, индекс по случайному флоту ничего не даст.

Добавлено через 4 минуты и 45 секунд
Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
default NULL

везде, где возможно замените на значение (0, 0.0) это некоторые излишние проверки минимизирует
PM MAIL   Вверх
shevak
Дата 14.12.2010, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Сделал тестовый скрипт для проверок нагрузок. Скрипт имитирует совершение ставки пользователем. Примерно 15 запросов. Со вставкой записи, чтение таблицы ставок и т.п. Запускал 500 запросов, параллельно 10. Результат:

Добавлено через 4 минуты и 9 секунд
InnoDb - 53 секунды
MyISAM - 22 екунды
если сделать отдельную таблицу для каждого аукциона - 8 секунд на MyISAM

Да, status - 0, 1, 2. TinyInt (2) подойдет, спс.

Аукцион закрывается 3 раза в неделю. Максимум открытых аукционов - 9. По этому для каждого открыть отдельную таблицу не так чревато. Если это ускорит работу в 3 раза, как показали тесты. После закрытия аукциона ставки перенесутся в общую таблицу rates_close и отдельная таблица удалится.
PM MAIL   Вверх
skyboy
Дата 14.12.2010, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 41
Всего: 260



предлагаю попробовать такое: использование mysql как nosql
PM MAIL   Вверх
triclosan
Дата 14.12.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 18.8.2006

Репутация: 1
Всего: 12



Цитата(shevak @  14.12.2010,  16:41 Найти цитируемый пост)
Максимум открытых аукционов - 9

а когда их станет 109? 

Цитата(shevak @  14.12.2010,  16:41 Найти цитируемый пост)
отдельная таблица удалится. 

если гарантированно 9, то зачем удалять, просто очищайте. Если уже на то пошло - создайте вспомогательную таблицу статусов, где будет указано что и как в каждой из 9ти. 

Как я понял, у вас достаточно стандартный SQL, следовательно можно пощупать другие реляционные СУБД, смысл в этом обрисуется, когда открытых аукционов станет 1009  smile 
PM MAIL   Вверх
shevak
Дата 14.12.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Почитаю, отпишусь

Добавлено через 8 минут и 11 секунд
triclosan, т.е. хочешь сказать, что мускулу такие нагрузки не под силу? что такое 10 вставок в секунду - чепуха
PM MAIL   Вверх
skyboy
Дата 14.12.2010, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 41
Всего: 260



хотя, нет. рекомендую начать с "set profiling=1", чтоб выяснить, на каком именно этапе тормоза появляются.
PM MAIL   Вверх
triclosan
Дата 14.12.2010, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 18.8.2006

Репутация: 1
Всего: 12



Цитата(shevak @  14.12.2010,  17:00 Найти цитируемый пост)
что такое 10 вставок в секунду - чепуха 

Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
Сервер должен бы с таким справиться, но увы (((. 


PM MAIL   Вверх
shevak
Дата 14.12.2010, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Цитата(triclosan @ 14.12.2010,  17:21)
Цитата(shevak @  14.12.2010,  17:00 Найти цитируемый пост)
что такое 10 вставок в секунду - чепуха 

Цитата(shevak @  14.12.2010,  13:23 Найти цитируемый пост)
Сервер должен бы с таким справиться, но увы (((. 

значит что-то не так делаю. Или мускул такой слабый, что не выдержит 10 вставок в секунду? 


Да, еще вопрос. На сервере стоит мускул 5.0 Есть смысл переходить 5.1. И это что-то повредит или смело переходить, там серьезных изменений нет?

Добавлено через 4 минуты и 4 секунды
skyboy, тормоза появляются на запросах 
Код

SELECT id FROM wla_rates WHERE auction_id=439 AND user_id=18452 AND sum=61.17 

и 
Код

INSERT INTO wla_rates (user_id,auction_id,sum,status) VALUES(18452,439,61.17,1)


Кстати поставил полю status - tinuint(1) и убрал кавычка в запросах - время выполнения уменьшилось с 22 сек до 15 сек для цельной таблицы.

Так идея разделить таблицы - это бред? не стоит такое делать?

Добавлено через 10 минут и 5 секунд
т.к. для отдельной таблицы для аукциона сейчас время выполнения 500 ставок уменьшилось до 3.5 секунд. Но в отдельных таблицах опасный вопрос - это пересечение ай-ди ставок. Не угадаешь на перед сколько будет на 1 аукцион. Сегодня например эта цифра 50 000 ставок, а неделю назад была 15 000 ставок
PM MAIL   Вверх
triclosan
Дата 14.12.2010, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 515
Регистрация: 18.8.2006

Репутация: 1
Всего: 12



Цитата(shevak @  14.12.2010,  17:30 Найти цитируемый пост)

значит что-то не так делаю. Или мускул такой слабый, что не выдержит 10 вставок в секунду? 

слабый, но вообще-то не настолько


Цитата(shevak @  14.12.2010,  17:30 Найти цитируемый пост)
 AND sum=61.17 

этого никак не избежать, можно чего-то додумать чтобы с double не сравнивать?


Цитата(shevak @  14.12.2010,  17:30 Найти цитируемый пост)
INSERT INTO wla_rates (user_id,auction_id,sum,status) VALUES(18452,439,61.17,1)

вот это интересно, стоит подумать это именно тормозит - софт или железо.



Цитата(shevak @  14.12.2010,  17:30 Найти цитируемый пост)
Так идея разделить таблицы - это бред? не стоит такое делать? 

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

Это сообщение отредактировал(а) triclosan - 14.12.2010, 17:45
PM MAIL   Вверх
baldina
Дата 14.12.2010, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



1. сделать индексы по status, sum. ASC или DESC никакой роли не играет
2. сделать sum NOT NULL (default 0)
3. (если возможно) изменить тип sum на INT, сохраняя умноженные на 100 значения
4. каков размер БД? Нельзя ли для текущей работы использовать HEAP, копируя, при необходимости, в постоянную таблицу (например, после торгов)
PM MAIL   Вверх
shevak
Дата 14.12.2010, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



По поводу предыдущих запросов - все в порядке. помог индекс на поле sum и изменение поля stаsus на  tinyint

Сейчас глючит вот такой запрос
Код

SET @n:=0, @found:=0;
SELECT IF(@found = 1 OR id=1283086, @found:=1, @n:=@n+1) FROM rates WHERE auction_id=439 AND status=1 ORDER BY sum DESC
SELECT @n AS num;


Он определяет место ставки в выборке. Других вариантов не придумал. Даже на форуме спрашивал, ничего более подходящего нет. Но этот запрос тормозит.
PM MAIL   Вверх
shevak
Дата 14.12.2010, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Вот это я дурак. Эти запросы можно заменить на запрос 
Код

SELECT COUNT(*) FROM rates WHERE auction_id = 439 AND status = 1 AND sum > 'сумма ставки 1283086'


Так и сделал и добавил еще один индекс по полям auction_id, status, sum. Время выполнения 500 ставок стало 1.6 сек. И как после такого в чудеса не верить. ))

Спасибо большое всем за помощь
PM MAIL   Вверх
shevak
Дата 15.12.2010, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.8.2008

Репутация: нет
Всего: 1



Все, да не все. Остался запрос
Код

SELECT r.*, u.id as u_id, u.city, u.nikname 
FROM rates as r 
LEFT JOIN users as u ON u.id=r.user_id 
WHERE r.auction_id=439 ORDER BY status,sum DESC,r.id LIMIT 0,25


Он не оптимизируется никак. Как ни крути, а все-равно выборка идет по всей таблице с auction_id=439. Тут ничего нельзя сделать?

Это сообщение отредактировал(а) shevak - 15.12.2010, 00:10
PM MAIL   Вверх
baldina
Дата 15.12.2010, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



должен работать быстро.

Добавлено через 11 секунд
поле sum NOT NULL DEFAULT 0 сделал?
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




[ Время генерации скрипта: 0.1008 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.