вопрос по php и mysql, логика, помогите.

12 3
gr1nader
На сайте с 26.10.2012
Offline
20
1154

вопрос есть некая база пользователей с таблицей в которой более 100000 строк (пользователей), каждая строка проверяется ежечасно неким скриптом на активность в последний час и если был активен то в колонке "activ" ставится "1" если нет то "0", ну это по идее на самом деле есть только масив активных поэтому делаю так:

$query = "UPDATE users SET `activ` = '0'";
mysql_query($query) or die ("Error in query: $query");

//$good - masiv so vsemi aktivnymi s proverki
foreach ($good as $id){
$query = "UPDATE users SET `activ` = '1' WHERE `username` = '$id'";
mysql_query($query) or die ("Error in query: $query");
}

получается что в момент проверки таблица обнуляется, у всех проставляю в "activ" 0, а потом из масива полученног с проверки всех активных проставляются "1" в "activ" т.е фактически есть пару минут когда в базе активных пользователей 0 и это значение постепенно растет до момента проставления всех "1" в колонке "activ".

как избежать ситуации с нулевым показателем активных пользователей в эти пару минут пока проставляются "1" в колонке "activ"???

пробывал сделать так:

foreach ($good as $id){
$query = "UPDATE users SET `activ` = '1' WHERE `username` = '$id'";
mysql_query($query) or die ("Error in query: $query");
}
foreach ($good as $id){
$query = "UPDATE users SET `activ` = '0' WHERE `username` <> '$id'";
mysql_query($query) or die ("Error in query: $query");
}

но чтото не пошло у всех проставились "0" в "activ" в конце исполнения.

прошу сильно не пинать )) можно с кошельком в ЛС за вознаграждение.

спасибо.

OK
siv1987
На сайте с 02.04.2009
Offline
427
#1
gr1nader:

как избежать ситуации с нулевым показателем активных пользователей в эти пару минут пока проставляются "1" в колонке "activ"???

Пара минут?

Каким образом проверяется? Откуда массив good?

gr1nader
На сайте с 26.10.2012
Offline
20
#2

siv1987, сложно объяснять происодит ряд подключений к сторонним серверам, но может не пару но минуту точно и это после переезда на дедик, на впс реально занимало минуты 2-3

вот код проверки:

функция multicurlcheck своя производит саму проверку:

$good = array();
$cnt = count( $all_users) / 500;
for( $i = 0; $i < $cnt; $i++ )
$good = array_merge( $good, multicurlcheck( $location, array_slice( $all_users, $i * 500, 500 ), 10 ) );
siv1987
На сайте с 02.04.2009
Offline
427
#3

Сколько пользователей обычно онлайн? Может есть смысл разбить на подгруппы и делать IN-ом в несколько запросов?

gr1nader
На сайте с 26.10.2012
Offline
20
#4

siv1987, обычно около 1-2% активных но разных, всетаки склоняюсь к решению моему второму :

foreach ($good as $id){
$query = "UPDATE users SET `activ` = '1' WHERE `username` = '$id'";
mysql_query($query) or die ("Error in query: $query");
}
foreach ($good as $id){
$query = "UPDATE users SET `activ` = '0' WHERE `username` <> '$id'";
mysql_query($query) or die ("Error in query: $query");
}

но почемуто проставляются "0" в актив, не страшно если какоето время в базе будут активные с прошлой и с текущей проверки вместе, а в течении 1-2 минут проставятся нули у неактивных по последней проверки, страшнее когда в базе у всех "0" в активе а потом по возрастающей.

EA
На сайте с 15.06.2006
Offline
70
#5

не обязательно обнулять всех. обнулить надо только тех, у кого был activ=1. может быть это будет быстрее чем пробегать по всем строкам и сравнивать id с активным.

siv1987
На сайте с 02.04.2009
Offline
427
#6
e-art:
не обязательно обнулять всех. обнулить надо только тех, у кого был activ=1. может быть это будет быстрее чем пробегать по всем строкам и сравнивать id с активным.

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

gr1nader:
страшнее когда в базе у всех "0" в активе а потом по возрастающей.

Покажите ради интереса структуру таблицы.

И хорошо было бы увидеть профилинг запроса UPDATE users SET `activ` = 0;

---------- Добавлено 11.06.2013 в 22:32 ----------

gr1nader:
всетаки склоняюсь к решению моему втором


mysql_query('UPDATE users SET activ=0');

$names = array_chunk($good, 100);
foreach($names as $nam)
{
mysql_query('UPDATE users SET activ=1 WHERE username IN ("'.implode('", "', $nam).'"');
}
gr1nader
На сайте с 26.10.2012
Offline
20
#7
e-art:
не обязательно обнулять всех. обнулить надо только тех, у кого был activ=1. может быть это будет быстрее чем пробегать по всем строкам и сравнивать id с активным.

тормоз не на

" UPDATE users SET `activ` = 0;"
это происходит мгновенно, а именно потом на "
foreach ($good as $id){
$query = "UPDATE users SET `activ` = '1' WHERE `username` = '$id'";
mysql_query($query) or die ("Error in query: $query");
}

т.е пока пробежит по всей базе и проставит "1" у всех кто из масива $good

siv1987
На сайте с 02.04.2009
Offline
427
#8

Структуру таблицы ждем в студию.

Еще как вариант создать временную таблицу, загнать туда данные и сравнивать с ней.

gr1nader
На сайте с 26.10.2012
Offline
20
#9

siv1987, вот структура если это вы имели ввиду:

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`active` varchar(10) DEFAULT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=100568;
siv1987
На сайте с 02.04.2009
Offline
427
#10

Без индекса на username... 100K записей... Зачем так жить?!

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

100K строк и автоинкремент на 40K, это как?

Почему UNIQUE а не PRIMARY?

12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий