SELECT / UPDATE и SELECT / INSERT убивают сервер MySQL - PullRequest
3 голосов
/ 21 июля 2010

Я управляю сервером, который убивается из-за количества запросов, которые он получает от одной из наших игр для iPhone для хранения результатов. Я имею в виду, что сервер перестает отвечать на запросы.

Я действительно знаю достаточно MySQL / PHP, чтобы обойтись, поэтому я пытаюсь исправить это. Я уверен, что это проблема, которую можно оптимизировать, потому что у нас есть выделенный сервер. Мы обрабатываем только 300 запросов в минуту.

В основном мы проверяем счет, который кто-то публикует в своей игре на iPhone (используя SELECT), чтобы увидеть, есть ли у него уже существующий счет. Если они делают, и их новый счет лучше, мы делаем ОБНОВЛЕНИЕ, в противном случае мы делаем ВСТАВКУ. Заявления выглядят так:

$ sql = "ВЫБЕРИТЕ id, счет, уровень ИЗ таблицы $ ГДЕ доска = '$ board' И имя = '$ name' И udid = '$ udid' AND fbuid = '$ fbuid'"

Операторы UPDATE и INSERT выглядят так:

$ sql = "UPDATE $ table SET SET Score =" $ Score ", уровень =" $ level ", страна =" $ страна ", дата = CURRENT_TIMESTAMP WHERE board = '$ board' AND name = '$ name' AND udid = '$ udid' AND fbuid = '$ fbuid' "

$ sql = "INSERT INTO $ таблица (доска, udid, fbuid, имя, оценка, уровень, страна). оценка ',' уровень $, $ страна ') "

А для полноты вот определение таблицы:

CREATE TABLE $table (
id int (11) NOT NULL auto_increment,
board tinyint (4) NOT NULL,
udid varchar (45) по умолчанию NULL,
fbuid bigint (20) без знака по умолчанию NULL,
name varchar (25) по умолчанию NULL,
country tinyint (4) по умолчанию NULL,
level tinyint (4) по умолчанию NULL,
score десятичное (10,0) значение по умолчанию NULL,
date отметка времени NOT NULL по умолчанию CURRENT_TIMESTAMP,
ПЕРВИЧНЫЙ КЛЮЧ (id),
КЛЮЧ scoreidx (score),
КЛЮЧ udididx (udid),
КЛЮЧ fbuididx (fbuid),
КЛЮЧ boardidx (board),
КЛЮЧ levelidx (level),
КЛЮЧ countryidx (country)
) ДВИГАТЕЛЬ = CHISSET ПО УМОЛЧАНИЮ MyISAM = латиница 1

В настоящее время я подключаюсь к серверу MySQL из PHP, используя:

$ conn = mysql_pconnect (DB_HOST, DB_USER, DB_PASSWORD, MYSQL_CLIENT_INTERACTIVE);

Но раньше использовал msql_connect, но не заметил улучшения с этим.

Любые указатели на то, как я могу оптимизировать это, или ссылки на любые веб-страницы, которые описывают то, что я должен делать, будут с благодарностью приняты.

Ответы [ 3 ]

4 голосов
/ 21 июля 2010

MyISAM имеет блокировки таблиц вместо блокировок строк InnoDB.Вы можете создать копию своей таблицы, изменить двигатель на InnoDB и (на тестовом сервере) протестировать нагрузку с помощью mysqlslap или аналогичных инструментов стресс-тестирования.

Также очень важно:

ALTER TABLE tablename ADD INDEX(board,name,udid,fbuid)

MySQL может использовать только 1 индекс за раз, поэтому ваши несколько «свободных» индексов не так уж хороши, когда всегда запрашивают эту конкретную комбинацию.

1 голос
/ 21 июля 2010

"MySQL использует блокировку на уровне таблицы для Таблицы MyISAM, MEMORY и MERGE, блокировка на уровне страниц для таблиц BDB и блокировка на уровне строк для таблиц InnoDB. "

http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html

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

0 голосов
/ 21 июля 2010

вы можете попытаться оптимизировать, не делая выбор и обновляя дублирующийся первичный ключ. Вам понадобится первичный ключ, такой как адрес электронной почты или что-то еще.

$sql = "INSERT INTO $table(board, udid, fbuid, name, score, level, country) VALUES
('$board', '$udid', '$fbuid', '$name', '$score', '$level', $country') ON DUPLICATE KEY
UPDATE score = '$score'";
...