Самым быстрым образом апдейт выполнится, когда есть индексы по тому, что участвует в WHERE и нет индексов по всему остальному. Первое гораздо значительнее. Выводы делайте сами. (Добавление)
Phantik пишет:
1) Попробовать BLOB поле заменить на текстовое ибо тип хранимых данных это позволяет сделать
Обязательно. (Добавление)
А вообще, написано очень много.
BLOB на char(n) заменил. Прирост получился несущественный.
Все поля которые в WHERE являются составным Primary Key т.е. я так понимаю индексированы автоматически. Поля которые обновляются - без индексов.
Есть аналогичная структура таблиц\запросов под MSSQL и MSAccess - запрос Update работает на порядок быстрее. Пытаюсь того же добиться на MySQL. (Добавление)
Сразу приношу извинения за большой текст. Задавал этот вопрос кратко на другом форуме, но людям не хватило информации, поэтому пришлось выложить более подробно:
Так устроен типичный запрос на поиск\проверку билета:
Таблица summ. В ней хранятся описания призов и денежные суммы призов. Записей в среднем 3-5 тысяч.
Связана с таблицей wins по полям LID, DrawNum, Module, Tour. Связь один(summ) ко многим(wins). Связь логическая, физически (средствами СУБД) не реализована.
`LID` smallint(6) unsigned NOT NULL, // Код лотереи
`DrawNum` smallint(6) unsigned NOT NULL, // Номер тиража
`Module` smallint(6) unsigned NOT NULL, // Код типа розыгрыша
`Tour` smallint(6) unsigned NOT NULL, // Тур
`Money` bigint(20) unsigned NOT NULL, // Сумма
`Descr1` char(64) DEFAULT NULL, // Текстовое описание приза
`Descr2` char(64) DEFAULT NULL, // Текстовое описание приза №2
PRIMARY KEY(`LID`,`DrawNum`,`Module`,`Tour`)
) ENGINE=MyISAM;
Таблица mods. В ней хранятся типы розыгрыша(особенности правил игры в определенном тираже)
Записей в среднем до 1000.
Связана с таблицей wins по полям LID,DrawNum,Module
Так вот. Первый запрос выполняется приемлимо быстро. В среднем 1-50 мили сек. Особенности работы оператора состоят в том что если билет выигрышный(т.е. первый запрос вернулся не пустым), то ему надо зафиксировать оплату билета. Т.е. проапдейтить поля PayDT, WorkST, CurTax в таблице wins. Для этого выполняется следующий запрос:
UPDATE wins SET PayDT=40044.4448122338,WorkST=1,CurTax=0
WHERE LID=1 AND DrawNum=532 AND TckNum=358015
Так вот. ПРоблема в том что этот запрос уже выполняется по времени порядка 1 секунды. Что абсолютно неприемлимо ибо скорость оператора по вводу билетов может достигать 3-4 билетов в секунду. Отсюда следует собственно вопрос, как существенно ускорить запрос на изменение. Уверен что это возможно т.к. базы аналогичной структуры в СУБД Access и MSSQL выполняют такой запрос практически на порядок быстрее.
Теперь какие у меня есть мысли по всему этому.
1) Попробовать BLOB поле заменить на текстовое ибо тип хранимых данных это позволяет сделать.
2) С учетом пункта 1) (или без учета) вынести Blob(текстовое) поле в другую таблицу. Связь будет по LID,DrawNum,TckNum
3) Создать временную таблицу Tmp со структурой аналогичной таблице wins и все фиксации оплаты заносить туда с Помощью INSERT. (Протестил добавление - оно работает приемлемо быстро порядка 500 записей в секунду). И далее(например перед закрытием программы) либо писать хитрый запрос на вроде(проапдейтить в wins те записи которые присутствуют в Tmp). Такой запрос с помощью SQL вроде можно написать. Либо запускать параллельный поток, который будет брать запись из Tmp апдейтить соответствующую в wins и удалять из Tmp.
4) Мне кажется, что есть среди настроек MySQL те, которые отвечают за работу с кешем. Что бы апдейты записывались не напрямую в базу(А судя по времени, у меня возникает ощущение что СУБД пишет напрямую), а через кеш. Очень надеюсь что знающие люди подскажут эти настройки.
Спасибо за советы. Впринципе свой метод тоже неплох правда, видимо, излишне будет нагружать Апач. Я вот думаю еще о таком варианте, как написать исполняемый клиент на C++ Builder(надо только скачать дополнительные дрова для конекта с MySQL) Ну а в проге по таймеру анализировать таблицы и вносить изменения . Правда тут есть свои нюансы - экзешник будет работать под виндой т.е. на юниксовых хостингах я не смогу запускать свой проект. И даже если хост виндовый, позволит ли фирма-хостер запускать на своих серваках различные мои экзешники? Так же пока не совсем представляю как будет выглядеть удаленное управление мои экзешником.
Ладно.... Пока все это обсуждалось, у меня появилась еще одна проблема. Решить я ее смог как то случайно, но вот смысла, почему так происходит, не понял.
Вообщем тот файл control.php к которому каждые несколько секунд обращалась страница таймер(см. 1ый пост) имел следущую структуру:
<html>
<head>
</head>
<body>
<?php
function ABC($ID)
{
$query = "SELECT ......";
$resylt = mysql_query($query, $link);
//.............................
// Другие действия с базой
//.............................
}
// Некие действия с базой
//.............................. ..
$ID = line['Player_ID'];
switch($a)
{
case 1 : ABC($ID);
break;
case 2: //........
break;
//......................
Проблема была в следущем: Выполнялись все действия в PHP коде(Некие действия с базой) но в функцию ABC() скрипт не заходил ни в какую. "Другие действия с базой" - не выполнялись. Мучался пол дня, код заработал только тогда когда заменил строку
Отсюда сделал вывод что пересылка на другую страницу выполнялась раньше чем вызывалась функция. Причем странно еще то, что весь PHP код успевал выполняться до пересылки, кроме кода внутри функции. Отложив пересылку на 3 секунды, стал успевать выполняться весь код.
кто знает в чем тут фича? Почему код выполняется как-то непоследовательно совсем?
спасет ли ситуацию замена строки
<script> setTimeout("location.href='timer.html'",3000)</script>
на <?php echo '<script> location.href="timer.html"'; </script>
если разместить ее в самом конце основного PHP кода?
Здравствуйте форумчане. Я тут человек новый, поэтому прошу не судить строго за, возможно, примитивные вопросы.
Проблема в следующем. В контексте создания браузерной игры столкнулся с задачей необходимости обработки данных на сервере в ситуациях когда от клиентов не поступает запростов вообще, но при этом обрабатывать данные нужно. Банальный пример: Я отправляю свою армию на врага и прийти она должна допустим через 3 часа. Рассматривается ситуация, когда ни меня ни противника(на которого я отправил армию) нету у компа вообще. Но тем не менее, должен отработать скрипт который обсчитает битву и запишет в базу данных всю информацию о результатах данного события(битвы).
Я только недавно начал изучать PHP и пока у меня нет идеи как реализовать такую задачу. У меня пока сложилось жесткое представление об работе PHP связанное с четкой логикой: запрос клиента -> ответ сервера. Т.е. у меня каждая страница делится на 2 состовляющие:
1) html(php) страница - которую показываем клиенту.
2) php страница обрабатывающая страницу из пункта 1.
(иногда пункты 1 и 2 совмещены физически в одной странице)
Казалось бы все хорошо, но начали возникать на серверной стороне задачи, которые необходимо выполнять не по запросу клиента, а в определенные моменты времени.
Я немного погорячился, сказав что нету идеи. Идея есть и я ее даже реализовал и она работает следующим образом. Все события которые должны произойти сами по себе в некоторое определенное время, независимо от запроса пользователя, я записываю в специальную таблицу MySQL. Одно из полей в этой таблице - это время, когда надо обработать данное событие. Дальше я сделал страничку не входящую в сайт самой игры, но каждые несколько секунд (через JavaScript таймер ) она обращается к некому php файлу. В этом файле делается запрос к таблице событий и если в ней есть записи событий время которых настало, они в цикле обрабатываются соответствующими функциями, после чего результаты записываются в базу.
Вообщем задачу то я выполнил, но как-то это все каряво выглядит. Наверняка в PHP есть возможность все это реализовать без левой странички, непрерывно бомбящей сервер своими запросами. Мне кажется что все это можно реализовать гораздо проще, и красивее какими-нить возможностями PHP про которые я еще не знаю. Кто-нибудь может мне посоветовать в какой области копать? Наверняка многие уже сталкивались со схожими задачами.
Заранее благодарен за ответы.