powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Оптимизация Postgres для огромных таблиц
16 сообщений из 16, страница 1 из 1
Оптимизация Postgres для огромных таблиц
    #33693325
postt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что нужно сделать,чтобы оптимизировать работы Postgres на огромных таблицах. Например долго выполняется запрос вида ( причем операции с индексом тоже работают долго)
EXPLAIN SELECT sum(bytes)::double precision,to_char(date_trunc('day',second),'DD')::text AS ds,name,clients2.id FROM iptables,net_addr,clients2 WHERE net_addr.ip::inet=iptables.dest::inet and clients2.id::int=net_addr.id::int and second BETWEEN '2006-04-01 00:00:00'::date and '2006-04-10 00:00:00'::date GROUP BY clients2.id::int,name::text,ds ORDER BY name,ds;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=132056.49..132544.72 rows=195292 width=36)
Sort Key: clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
-> GroupAggregate (cost=103396.11..109739.93 rows=195292 width=36)
-> Sort (cost=103396.11..104371.93 rows=390331 width=36)
Sort Key: clients2.id, clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
-> Hash Join (cost=56.63..42555.41 rows=390331 width=36)
Hash Cond: ("outer".dest = "inner".ip)
-> Index Scan using idx_second on iptables (cost=0.00..34692.16 rows=390331 width=27)
Index Cond: (("second" >= '2006-04-01 00:00:00'::timestamp without time zone) AND ("second" <= '2006-04-10 00:00:00'::timestamp without time zone))
-> Hash (cost=54.26..54.26 rows=947 width=31)
-> Hash Join (cost=20.59..54.26 rows=947 width=31)
Hash Cond: ("outer".id = "inner".id)
-> Seq Scan on net_addr (cost=0.00..19.47 rows=947 width=15)
-> Hash (cost=18.47..18.47 rows=847 width=20)
-> Seq Scan on clients2 (cost=0.00..18.47 rows=847 width=20)
(15 rows)
EXPLAIN SELECT sum(bytes)::double precision,to_char(date_trunc('day',second),'DD')::text AS ds,name,clients2.id FROM iptables,net_addr,clients2 WHERE net_addr.ip::inet=iptables.dest::inet and clients2.id::int=net_addr.id::int and second BETWEEN '2006-04-01 00:00:00'::date and '2006-04-10 00:00:00'::date GROUP BY clients2.id::int,name::text,ds ORDER BY name,ds;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=132056.49..132544.72 rows=195292 width=36)
Sort Key: clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
-> GroupAggregate (cost=103396.11..109739.93 rows=195292 width=36)
-> Sort (cost=103396.11..104371.93 rows=390331 width=36)
Sort Key: clients2.id, clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
-> Hash Join (cost=56.63..42555.41 rows=390331 width=36)
Hash Cond: ("outer".dest = "inner".ip)
-> Index Scan using idx_second on iptables (cost=0.00..34692.16 rows=390331 width=27)
Index Cond: (("second" >= '2006-04-01 00:00:00'::timestamp without time zone) AND ("second" <= '2006-04-10 00:00:00'::timestamp without time zone))
-> Hash (cost=54.26..54.26 rows=947 width=31)
-> Hash Join (cost=20.59..54.26 rows=947 width=31)
Hash Cond: ("outer".id = "inner".id)
-> Seq Scan on net_addr (cost=0.00..19.47 rows=947 width=15)
-> Hash (cost=18.47..18.47 rows=847 width=20)
-> Seq Scan on clients2 (cost=0.00..18.47 rows=847 width=20)
(15 rows)
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33693440
AlexTheRaven
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Память проверяли?
В файле postgresql.conf есть раздел resourse usage->memory. В нём есть параметры work_mem, maintenance_work_mem, max_stack_depth. По умолчанию там стоят до смешного маленькие значения. Попробуйте увеличить их раз в 10-20.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33693458
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Посмотреть в сторону Partitioning.
http://www.postgresql.org/docs/8.1/interactive/ddl-partitioning.html
Очень помогает.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33693528
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А explain analyze можно? И оборачивай explain как сырцы (кнопочка SRC при написании топика).
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33693979
postt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
EXPLAIN ANALYZE SELECT sum(bytes),to_char(date_trunc('day',second),'DD'),name,clients2.id FROM iptables,net_addr,clients2 WHERE ((net_addr.ip=iptables.dest) and (clients2.id=net_addr.id)) and second  BETWEEN '2006-04-01' and '2006-04-30' GROUP BY clients2.id,name,to_char(date_trunc('day',second),'DD')  ORDER BY name,to_char(date_trunc('day',second),'DD');
                                                                                  QUERY PLAN                                                                                                                
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost= 378593 . 39 .. 380048 . 91  rows= 582207  width= 36 ) (actual time= 48179 . 569 .. 48192 . 531  rows= 21107  loops= 1 )
   Sort Key: clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
   ->  GroupAggregate  (cost= 284606 . 30 .. 303518 . 66  rows= 582207  width= 36 ) (actual time= 43915 . 575 .. 47847 . 327  rows= 21107  loops= 1 )
         ->  Sort  (cost= 284606 . 30 .. 287515 . 46  rows= 1163664  width= 36 ) (actual time= 43915 . 373 .. 44749 . 620  rows= 606917  loops= 1 )
               Sort Key: clients2.id, clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
               ->  Hash Join  (cost= 56 . 63 .. 126750 . 74  rows= 1163664  width= 36 ) (actual time= 8 . 044 .. 11124 . 963  rows= 606917  loops= 1 )
                     Hash Cond: ("outer".dest = "inner".ip)
                     ->  Index Scan using idx_second on iptables  (cost= 0 . 00 .. 103420 . 83  rows= 1163664  width= 27 ) (actual time= 0 . 187 .. 3623 . 816  rows= 1191591  loops= 1 )
                           Index Cond: (("second" >= '2006-04-01 00:00:00'::timestamp without time zone) AND ("second" <= '2006-04-30 00:00:00'::timestamp without time zone))
                     ->  Hash  (cost= 54 . 26 .. 54 . 26  rows= 947  width= 31 ) (actual time= 7 . 620 .. 7 . 620  rows= 0  loops= 1 )
                           ->  Hash Join  (cost= 20 . 59 .. 54 . 26  rows= 947  width= 31 ) (actual time= 2 . 544 .. 6 . 386  rows= 948  loops= 1 )
                                 Hash Cond: ("outer".id = "inner".id)
                                 ->  Seq Scan on net_addr  (cost= 0 . 00 .. 19 . 47  rows= 947  width= 15 ) (actual time= 0 . 004 .. 0 . 994  rows= 948  loops= 1 )
                                 ->  Hash  (cost= 18 . 47 .. 18 . 47  rows= 847  width= 20 ) (actual time= 2 . 383 .. 2 . 383  rows= 0  loops= 1 )
                                       ->  Seq Scan on clients2  (cost= 0 . 00 .. 18 . 47  rows= 847  width= 20 ) (actual time= 0 . 016 .. 1 . 389  rows= 849  loops= 1 )
 Total runtime:  48221 . 441  ms
(записей:  16 )

Когда Postgres считает суммы в этом запросе,он сканирует всю таблицу или только часть,ограниченную датой.Если эту часть,то имеет смысл создать Partitioning,а если нет,то не знаю чем он поможет.
В БД сейчас около 10 млн записей,но число постоянно растет.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33694463
Алексей Ключников
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Партиции можно сделать по клиентам.

А кто что скажет по партициям например по подсетям? :)
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33696610
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я думаю: вначале группируй по iptables.dest, а потом связывай с клиентами:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT sum(b.bytes), to_char(day, 'DD'), cl.name, cl.id
FROM (
SELECT sum(bytes) as bytes,date_trunc('day',second) as day, dest FROM iptables
WHERE second BETWEEN '2006-04-01' and '2006-04-30'
GROUP BY dest, date_trunc('day', second)
) b
JOIN net_addr na ON na.ip = b.dest
JOIN clients2 cl ON na.id = cl.id
GROUP BY cl.id, cl.name, day
ORDER BY name, day

А значения work_mem и shared_buffers в postgresql.conf каковы (как правильно заметил AlexTheRaven)? Shared Buffers - в твоем случае наверно под гектар стоит выделить ( - на сколько за месяц объем данных увеличивается - чтобы сразу весь месяц в памяти держать) (и вообще: какая железка/ось?).
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33696685
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
posttЧто нужно сделать,чтобы оптимизировать работы Postgres на огромных таблицах. Например долго выполняется запрос вида ( причем операции с индексом тоже работают долго)Нужно не работать с огромными таблицами. Например, если у вас в таблицу iptables добавляются строки с second~=now() и впоследствии не изменяются и не удаляются, то можно один раз в сутки чуть позже полуночи делать "insert into daily_stat_1 as select clients2.id, clients2.name, sum(bytes)::double precision as bytes, to_char(date_trunc('day',second),'DD')::text AS ds from ... where second between now()-'1 day' and now()" и затем делать выборки из этой таблицы.

postt
Код: plaintext
1.
2.
3.
4.
5.
   ->  GroupAggregate  (cost=284606.30..303518.66 rows=582207 width=36) (actual time=43915.575..47847.327 rows=21107 loops=1)
         ->  Sort  (cost=284606.30..287515.46 rows=1163664 width=36) (actual time=43915.373..44749.620 rows=606917 loops=1)
               Sort Key: clients2.id, clients2.name, to_char(date_trunc('day'::text, iptables."second"), 'DD'::text)
...
                     ->  Index Scan using idx_second on iptables  (cost=0.00..103420.83 rows=1163664 width=27) (actual time=0.187..3623.816 rows=1191591 loops=1)
                           Index Cond: (("second" >= '2006-04-01 00:00:00'::timestamp without time zone) AND ("second" <= '2006-04-30 00:00:00'::timestamp without time zone))

Когда Postgres считает суммы в этом запросе,он сканирует всю таблицу или только часть,ограниченную датой.В сортировку и группировку приходит 600 тыс строк - с учетом ограничения по дате, которое накладывается ранее при IndexScan.

P.S.: кстати, из миллиона с лишним строк полученных в IndexScan остаются только 600 тыс. оставшиеся не тарифицируются? это ошибка?

Funny_FalconЯ думаю: вначале группируй по iptables.dest, а потом связывай с клиентами:Я уже давал ему такой совет. http://sql.ru/forum/actualthread.aspx?tid=268827#2453909

Но здесь принципиального ускорения по-моему можно ожидать лишь избавившись от сортировки работающей 36 секунд, что составляет 80% от времени выполнения запроса. Но тогда придется пробегать все строки в порядке dest и фильтровать их по second? Хотя можно попобовать HashJoin, такой совет я тоже давал. http://sql.ru/forum/actualthread.aspx?tid=268827#2444761
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33696910
AlexTheRaven
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBat
Но здесь принципиального ускорения по-моему можно ожидать лишь избавившись от сортировки работающей 36 секунд, что составляет 80% от времени выполнения запроса.
Теоретически можно построить индекс, в котором строки будут перечисляться в заранее определённом порядке, и при выборке вместо того, чтобы устраивать новую сортировку, просто пользоваться этим индексом. Как это реализовано в Postgres и реализовано ли вообще - не знаю, но можно посмотреть в этом направлении.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33696929
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexTheRaven LeXa NalBat
Но здесь принципиального ускорения по-моему можно ожидать лишь избавившись от сортировки работающей 36 секунд, что составляет 80% от времени выполнения запроса.Теоретически можно построить индекс, в котором строки будут перечисляться в заранее определённом порядке, и при выборке вместо того, чтобы устраивать новую сортировку, просто пользоваться этим индексом. Как это реализовано в Postgres и реализовано ли вообще - не знаю, но можно посмотреть в этом направлении.Если ограничения по second заранее неизвестны, то есть нужно чтобы быстро работали запросы "where second between A and B group by dest" и "where second between C and D group by dest", то такого индекса по-меому построить нельзя.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33697397
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно для начала поменять местами dest и date_trunc
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT sum(b.bytes), to_char(day, 'DD'), cl.name, cl.id
FROM (
SELECT sum(bytes) as bytes,date_trunc('day',second) as day, dest FROM iptables
WHERE second BETWEEN '2006-04-01' and '2006-04-30'
GROUP BY date_trunc('day', second), dest
) b
JOIN net_addr na ON na.ip = b.dest
JOIN clients2 cl ON na.id = cl.id
GROUP BY cl.id, cl.name, day
ORDER BY name, day

Если second имеет тип timestamp (без tz), то можно построить индекс:
Код: plaintext
1.
2.
create index iptables_ix_day_dest on iptables
( (date_trunc('day',second)), dest);
и тогда
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT sum(b.bytes), to_char(day, 'DD'), cl.name, cl.id
FROM (
SELECT sum(bytes) as bytes,date_trunc('day',second) as day, dest FROM iptables
WHERE date_trunc('day', second) BETWEEN '2006-04-01' and '2006-04-30'
GROUP BY date_trunc('day', second), dest
) b
JOIN net_addr na ON na.ip = b.dest
JOIN clients2 cl ON na.id = cl.id
GROUP BY cl.id, cl.name, day
ORDER BY name, day
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33697426
postt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
600 тыс. из 1.2 млн возвращается из-за того,что это только строчки,соответствующие входящему трафику,а есть еще исходящий.Не совсем правильно нужно два поля в одной строке,но пока еще не сделал.
Об оборудовании:
cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Celeron(R) CPU 2.26GHz
stepping : 1
cpu MHz : 2260.319
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni monitor ds_cpl cid
bogomips : 4508.87
Памяти 512Мб.
OC ALTLinux 2.4.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33699287
postt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
EXPLAIN ANALYZE SELECT sum(b.bytes), to_char(day, 'DD'), cl.name, cl.id FROM ( SELECT sum(bytes) as bytes,date_trunc('day',second) as day, source FROM iptables WHERE date_trunc('day', second) BETWEEN '2006-04-01' and '2006-04-30' GROUP BY date_trunc('day', second), source ) b JOIN net_addr na ON na.ip = b.source JOIN clients2 cl ON na.id = cl.id GROUP BY cl.id, cl.name, day ORDER BY name, day;
                                                                                                              QUERY PLAN                                                                                                      
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost= 99176 . 61 .. 99207 . 69  rows= 12432  width= 36 ) (actual time= 11016 . 955 .. 11030 . 140  rows= 21912  loops= 1 )
   Sort Key: cl.name, b."day"
   ->  HashAggregate  (cost= 98268 . 96 .. 98331 . 12  rows= 12432  width= 36 ) (actual time= 10441 . 709 .. 10549 . 880  rows= 21912  loops= 1 )
         ->  Hash Join  (cost= 56 . 72 .. 98144 . 64  rows= 12432  width= 36 ) (actual time= 193 . 302 .. 10328 . 684  rows= 25909  loops= 1 )
               Hash Cond: ("outer".source = "inner".ip)
               ->  Subquery Scan b  (cost= 0 . 00 .. 97901 . 44  rows= 12432  width= 48 ) (actual time= 185 . 448 .. 10180 . 087  rows= 25997  loops= 1 )
                     ->  GroupAggregate  (cost= 0 . 00 .. 97777 . 12  rows= 12432  width= 27 ) (actual time= 185 . 442 .. 10108 . 389  rows= 25997  loops= 1 )
                           ->  Index Scan using iptables_ix_day_source on iptables  (cost= 0 . 00 .. 97530 . 55  rows= 24588  width= 27 ) (actual time= 0 . 258 .. 7592 . 128  rows= 1231689  loops= 1 )
                                 Index Cond: ((date_trunc('day'::text, "second") >= '2006-04-01 00:00:00'::timestamp without time zone) AND (date_trunc('day'::text, "second") <= '2006-04-30 00:00:00'::timestamp without time zone))
               ->  Hash  (cost= 54 . 35 .. 54 . 35  rows= 949  width= 31 ) (actual time= 7 . 525 .. 7 . 525  rows= 0  loops= 1 )
                     ->  Hash Join  (cost= 20 . 62 .. 54 . 35  rows= 949  width= 31 ) (actual time= 2 . 449 .. 6 . 367  rows= 952  loops= 1 )
                           Hash Cond: ("outer".id = "inner".id)
                           ->  Seq Scan on net_addr na  (cost= 0 . 00 .. 19 . 49  rows= 949  width= 15 ) (actual time= 0 . 052 .. 1 . 101  rows= 952  loops= 1 )
                           ->  Hash  (cost= 18 . 50 .. 18 . 50  rows= 850  width= 20 ) (actual time= 2 . 294 .. 2 . 294  rows= 0  loops= 1 )
                                 ->  Seq Scan on clients2 cl  (cost= 0 . 00 .. 18 . 50  rows= 850  width= 20 ) (actual time= 0 . 017 .. 1 . 341  rows= 854  loops= 1 )
 Total runtime:  11069 . 723  ms
(çàïèñåé:  16 )
Спасибо.Стало значительно быстрее работать.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33701017
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
                           ->  Index Scan using iptables_ix_day_source on iptables  (cost= 0 . 00 .. 97530 . 55  rows= 24588  width= 27 ) (actual time= 0 . 258 .. 7592 . 128  rows= 1231689  loops= 1 )
                                 Index Cond: ((date_trunc('day'::text, "second") >= '2006-04-01 00:00:00'::timestamp without time zone) AND (date_trunc('day'::text, "second") <= '2006-04-30 00:00:00'::timestamp without time zone))
Видимо здесь постгрес не использует второй столбец в индексе (source). Поэтому имеет смысл сделать индекс без него - меньше места на диске будет занимать => меньше чтений диска.
А если нужно быстро делать выборку по клиенту, то для PostgreSQL8.1 имеют смысл еще два отдельных индекса - по source и по dest.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33701149
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Funny_FalconВидимо здесь постгрес не использует второй столбец в индексе (source).Это поле используется, но не для выборки (фильтрации) по индексу, а благодаря ему отсутствует пересортировка перед GroupAggregate.
...
Рейтинг: 0 / 0
Оптимизация Postgres для огромных таблиц
    #33701635
Funny_Falcon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBatЭто поле используется, но не для выборки (фильтрации) по индексу, а благодаря ему отсутствует пересортировка перед GroupAggregate.
Был неправ, исправлюсь.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Оптимизация Postgres для огромных таблиц
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]