СУБД под BSD/UNIX: PostgreSQL, MySQL и другие. Установка, настройка, репликация, резервное копирование и оптимизация.
Модератор: terminus
Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-08-25 4:43:43
Существует кривой запрос:
Код: Выделить всё
UPDATE dbmail_messages SET deleted_flag ='1' WHERE mailbox_idnr =(SELECT message_idnr, dbmail_physmessage.internal_date, dbmail_messages.physmessage_id, unique_id, rfcsize, messagesize, seen_flag, answered_flag, deleted_flag, status FROM dbmail_messages LEFT JOIN dbmail_physmessage ON dbmail_messages.physmessage_id = dbmail_physmessage.id WHERE dbmail_messages.mailbox_idnr = (SELECT spambox FROM user_prefs) AND dbmail_messages.mailbox_idnr = (select message_idnr from dbmail_messages m join dbmail_mailboxes b ON
m.mailbox_idnr=b.mailbox_idnr JOIN dbmail_physmessage p ON
p.id=m.physmessage_id WHERE p.internal_date < 'NOW - 30 days' ) AND status=3 AND seen_flag=1;
как бы его улучьшить? (не надо мне ссылки на общее

Z301171463546 - можно пожертвовать мне денег
zingel
-
Хостинг HostFood.ru
-
Хостинг HostFood.ru
Тарифы на хостинг в России, от 12 рублей:
https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.:
https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах:
https://www.host-food.ru/domains/
-
Гость
- проходил мимо
Непрочитанное сообщение
Гость » 2009-08-25 6:33:36
zingel писал(а):как бы его улучьшить?
честно говоря с трудом верится, что он вообще работает
Код: Выделить всё
UPDATE
dbmail_messages
SET
deleted_flag ='1'
WHERE
mailbox_idnr =
(
SELECT
message_idnr,
dbmail_physmessage.internal_date,
dbmail_messages.physmessage_id,
unique_id,
rfcsize,
messagesize,
seen_flag,
answered_flag,
deleted_flag,
status
FROM
dbmail_messages
LEFT JOIN
dbmail_physmessage
ON
dbmail_messages.physmessage_id = dbmail_physmessage.id
WHERE
dbmail_messages.mailbox_idnr =
(
SELECT
spambox
FROM
user_prefs
)
AND
dbmail_messages.mailbox_idnr =
(
select
message_idnr
from
dbmail_messages m
join
dbmail_mailboxes b
ON
m.mailbox_idnr = b.mailbox_idnr
JOIN
dbmail_physmessage p
ON
p.id = m.physmessage_id
WHERE
p.internal_date < 'NOW - 30 days'
)
AND
status = 3
AND
seen_flag = 1;
элементарный подсчёт скобок показывает интригующее соотношение 3:2

Гость
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-08-25 6:34:42
элементарный подсчёт скобок показывает интригующее соотношение 3:2

ну в общем то да (после суток у меня они все на 1 лицо, ну и потом я опытный и у меня есть тестовая база - там не жалко и упустить) упростил до такого (вы тут не 1 маньяк);
Код: Выделить всё
UPDATE dbmail_messages SET deleted_flag=1,status=2 WHERE message_idnr IN (SELECT message_idnr FROM dbmail_messages m INNER JOIN dbmail_mailboxes b ON m.mailbox_idnr=b.mailbox_idnr INNER JOIN dbmail_physmessage p ON p.id=m.physmessage_id WHERE b.name LIKE 'SPAM' AND p.internal_date >= current_timestamp - interval '7 days');
задача запроса - удалять сообщения в папке spam которые старше 7 дней.
Годный на Ваш взгляд или можно как-то изящнее?
Z301171463546 - можно пожертвовать мне денег
zingel
-
Гость
- проходил мимо
Непрочитанное сообщение
Гость » 2009-08-25 6:48:16
Код: Выделить всё
UPDATE
dbmail_messages
SET
deleted_flag = 1,
status = 2
WHERE
message_idnr IN
(
SELECT
message_idnr
FROM
dbmail_messages m
INNER JOIN
dbmail_mailboxes b
ON
m.mailbox_idnr = b.mailbox_idnr
INNER JOIN
dbmail_physmessage p
ON
p.id = m.physmessage_id
WHERE
b.name LIKE 'SPAM'
AND
p.internal_date >= current_timestamp - interval '7 days'
);
при таком запросе данные из подзапроса попадут во временную таблицу без индекса, в результате услвие IN будет перебирать все данные подзапроса подряд. Тут будет логарифмическая зависимость между количеством данных и временем работы скрипта. Если же сделать отдельную временную таблицу с индексом по message_idnr, то зависимость станет линейная, что приведёт к заметному росту производительности на больших объёмах данных.
Гость
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-08-25 6:54:50
на самом деле это не столь Важно скрипт 1-2-3 разовый (к примеру упадёт бекэнд с филтрацией и всё будет лупиться как спам или какой паразит нагенерирует боунсов которые пометятся как спам e.t.c.) суть в том, что мне досталась база весом 6 гигабайт от старого админа и теперь порой нужно проходить по ящикам и убивать там старые письма, думаю написать скрипт и в крон его раз в месяц, то что он грузный это понятно, по этому 1 раз в месяц глубоко ночью.
Если с такой точки зрения, годный?
Z301171463546 - можно пожертвовать мне денег
zingel
-
Гость
- проходил мимо
Непрочитанное сообщение
Гость » 2009-08-25 7:03:09
zingel писал(а):Если с такой точки зрения, годный?
если работает, то вполне

Гость
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-08-25 7:18:20
Код: Выделить всё
dbmail=# UPDATE dbmail_messages SET deleted_flag=1,status=2 WHERE message_idnr IN (SELECT message_idnr FROM dbmail_messages m INNER JOIN dbmail_mailboxes b ON m.mailbox_idnr=b.mailbox_idnr INNER JOIN dbmail_physmessage p ON p.id=m.physmessage_id WHERE b.name LIKE 'SPAM' AND p.internal_date >= current_timestamp - interval '7 days');
UPDATE 28348
dbmail=#
отработал без нареканий....чего-то мне всеравно не нравиться что-то в нём, пока не понял что...ну вот вобщем кому нужно фунция(DBI:Pg)
1)Убивает ящики без пользователя
2)Не удалившиеся по какой-то причине
3)Чистящая спам (при желании можно вынести *spam* в отдельную переменную)
Код: Выделить всё
!/usr/bin/perl
use DBI();
use strict;
use warnings;
my $DBMA_dbname = "база";
my $DBMA_port = "3306";
my $DBMA_host = "хост";
my $DBMA_user = "юзер";
my $DBMA_password = "пароль";
my $sqltype = "pgsql";
my ( $message_idnr, $dbh, $sth );
if ($sqltype eq "pgsql")
{
unless (
$dbh = DBI->connect(
"DBI:Pg:user=$DBMA_user;password=$DBMA_password;dbname=$DBMA_dbname;port=$DBMA_port;host=$DBMA_host",
"$DBMA_user",
"$DBMA_user",
{ AutoCommit => 1 }
)
)
{
print "$DBI::errstr";
exit;
}
&dbmail_check4;
}
sub dbmail_check4 {
$sth =
$dbh->prepare(
"UPDATE dbmail_messages SET status = '003' where deleted_flag = '1' OR status >0"
);
$sth->execute();
$sth->finish();
$sth = $dbh->prepare(
"SELECT message_idnr from dbmail_messages
JOIN dbmail_mailboxes ON dbmail_messages.mailbox_idnr = dbmail_mailboxes.mailbox_idnr
LEFT JOIN dbmail_users ON dbmail_users.user_idnr = dbmail_mailboxes.owner_idnr
WHERE dbmail_users.user_idnr IS NULL"
);
$sth->execute();
while ( ($message_idnr) = $sth->fetchrow_array ) {
$sth =
$dbh->prepare(
"UPDATE dbmail_messages
SET deleted_flag=1,status=2
WHERE message_idnr IN
(SELECT message_idnr FROM dbmail_messages m
INNER JOIN dbmail_mailboxes b ON m.mailbox_idnr=b.mailbox_idnr
INNER JOIN dbmail_physmessage p ON p.id=m.physmessage_id
WHERE b.name LIKE 'SPAM' AND p.internal_date >=
current_timestamp - interval '7 days');"
);
$sth->execute();
}
$sth->finish();
$sth = $dbh->prepare(
"UPDATE dbmail_messages
LEFT JOIN dbmail_mailboxes ON dbmail_messages.mailbox_idnr = dbmail_mailboxes.mailbox_idnr
SET dbmail_messages.deleted_flag = '1', status = '001'
WHERE dbmail_mailboxes.mailbox_idnr IS NULL"
);
$sth->execute();
$sth->finish();
print "\nKill me?.\n
so sloooow.\n
(kill -9)\n\n";
exit;
}
Z301171463546 - можно пожертвовать мне денег
zingel
-
ss25
- мл. сержант
- Сообщения: 81
- Зарегистрирован: 2009-06-18 23:34:09
Непрочитанное сообщение
ss25 » 2009-11-07 23:02:24
Дурной тон выкладывать проблемные запросы без EXPLAIN ANALYZE.
ss25
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-11-08 0:45:34
да что Вы?
p.s. дурной тон пользовать чужие скрипты не подумав и не заточив под себя (с)
Z301171463546 - можно пожертвовать мне денег
zingel
-
ss25
- мл. сержант
- Сообщения: 81
- Зарегистрирован: 2009-06-18 23:34:09
Непрочитанное сообщение
ss25 » 2009-11-08 15:11:50
zingel писал(а):да что Вы?

Без комментариев.
zingel писал(а):
p.s. дурной тон пользовать чужие скрипты не подумав и не заточив под себя (с)
Не понял причем тут я.
========================>
ТС без обид как можно что либо улучшить не зная процессов происходящих внутри.
п.с. тема больше мне не интересна.
ss25
-
ProFTP
- подполковник
- Сообщения: 3388
- Зарегистрирован: 2008-04-13 1:50:04
- Откуда: %&й
-
Контактная информация:
Непрочитанное сообщение
ProFTP » 2009-11-08 15:14:06
оптимизировать можно по разному... разные запросы и разные нагрузки
тебе эти запросы нужны сейчас или кому? если да, то бери и оптимизируй...
может быть по некоторым причинам их не дедали идельаными, а по быстрому сделали на первый раз... а оптимизировать потом... и оптимизация запросов как правило делается в последний момент...
что тут не понятного?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'


ProFTP
-
Dirty.Eager
- мл. сержант
- Сообщения: 72
- Зарегистрирован: 2008-10-25 3:05:59
Непрочитанное сообщение
Dirty.Eager » 2009-11-08 16:52:42
zingel писал(а):элементарный подсчёт скобок показывает интригующее соотношение 3:2

ну в общем то да (после суток у меня они все на 1 лицо, ну и потом я опытный и у меня есть тестовая база - там не жалко и упустить) упростил до такого (вы тут не 1 маньяк);
Код: Выделить всё
UPDATE dbmail_messages SET deleted_flag=1,status=2 WHERE message_idnr IN (SELECT message_idnr FROM dbmail_messages m INNER JOIN dbmail_mailboxes b ON m.mailbox_idnr=b.mailbox_idnr INNER JOIN dbmail_physmessage p ON p.id=m.physmessage_id WHERE b.name LIKE 'SPAM' AND p.internal_date >= current_timestamp - interval '7 days');
задача запроса - удалять сообщения в папке spam которые старше 7 дней.
Годный на Ваш взгляд или можно как-то изящнее?
А что, нельзя без
IN обойтись? Вот так, например:
Код: Выделить всё
UPDATE dbmail_messages m
SET deleted_flag=1,
status=2
FROM dbmail_mailboxes b,
dbmail_physmessage p
WHERE m.mailbox_idnr=b.mailbox_idnr
AND p.id=m.physmessage_id
AND b.name LIKE 'SPAM'
AND p.internal_date >= current_timestamp - interval '7 days'
Dirty.Eager
-
zingel
- beastie
- Сообщения: 6204
- Зарегистрирован: 2007-10-30 3:56:49
- Откуда: Moscow
-
Контактная информация:
Непрочитанное сообщение
zingel » 2009-11-08 21:46:45
я просто думали что Вы хотите меня упрекнуть, сори
Z301171463546 - можно пожертвовать мне денег
zingel