Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Здравствуйте! Есть таблица, в которой хранится трафик. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Из этой таблицы нужно взять трафик для каждого client_id и поместить его в свой файл. client_id имеет около 16000 различных значений. Подскажите, как лучше выбирать данные? Записывать в файл будет скрипт либо на php, либо на python (еще не определился). Вариантов вижу несколько: 1. запрос для каждого client_id. Недостаток - очень много запросов. выполнение каждого запроса - около 3-4 секунд. 2. запрос для диапазонов - сначала от 1 до 100, затем от 101 до 200 и т.д. В скрипте можно будет открыть 100 файлов, и туда всё записать. Время выполнения одного запроса - 27секунд. 3. запрос всех данных. Не хочу загружать 6 гиг в оперативку. время выполнения не вычислял ;) 4. дамп таблицы и работа уже в текстовым файлом. время выполнения дампа - около 20 минут. Пока других вариантов не вижу, а хочется придумать, ибо такая задача будет выполняться каждую ночь. После создания таких файлов таблица будет удаляться. Надеюсь на ваши советы :) БД: PostgreSQL 8.3 Debian 4, 30Gb RAM, 4x2.8 CPU ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.10.2008, 21:22 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > Table "internet.trafic_20080901" > Column | Type | Modifiers > -----------+-----------------------------+------------------------ > ip_from | inet | not null > port_from | character varying(*10*) | not null > ip_to | inet | not null > bytes | bigint | not null > t_t | smallint | not null > place | smallint | not null > tm | timestamp without time zone | not null default now() > client_id | integer | not null > Indexes: > "trafic_20080901_client_idx" btree (client_id) > > В таблице 80млн. записей, размер таблицы - 6Гб. > Из этой таблицы нужно взять трафик для каждого client_id и поместить его > в свой файл. select * from internet.trafic_20080901 order by client_id бежать по запросу, и переписывать данные в куда надо. Как только будет меняться client_id, закрывать предыдущий файл клиента и открывать следующий. Перед выполнением запроса проверьте его план, и убедитесь в том, что сервер не будет сортировать данные, а будет использовать индекс. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.10.2008, 22:17 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MasterZiv, в этом случае все данные будут в память загружаться всей кучей, все 6 гигабайт. Думаешь, это оптимальный вариант? Код: plaintext 1. 2. 3. 4. 5. 6. Планировщик решил, что правильнее будет индекс не использовать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 08:03 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин ДмитрийMasterZiv, в этом случае все данные будут в память загружаться всей кучей, все 6 гигабайт. Думаешь, это оптимальный вариант? Код: plaintext 1. 2. 3. 4. 5. 6. Планировщик решил, что правильнее будет индекс не использовать. Возможно проблема в SELECT * Перечислите только те поля, которые действительно вам необходимы для суммирования. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 08:27 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Kruchinin Pahan, Даже если одно поле выбрать - все равно индекс не используется. Да и не много толку будет тут от индекса - все равно все данные загружать. Код: plaintext 1. 2. 3. 4. 5. 6. 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 09:46 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин ДмитрийKruchinin Pahan, Даже если одно поле выбрать - все равно индекс не используется. Да и не много толку будет тут от индекса - все равно все данные загружать. Значит, действительно нет необходимости. В реальности, иногда сортировка всей таблы ускоряется, если по индексу. Но, в общем-то MasterZiv прав. Данный способ может оказаться самым быстрым. Чтобы много памяти на клиенте не жрать, можно Fetch кусками делать (через курсор). И работать с небольшими блоками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 09:50 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > MasterZiv, в этом случае все данные будут в память загружаться всей > кучей, все 6 гигабайт. А ты можешь как-то обработать данные, не читая их в память ? Ну, давай, телепат ... Думаешь, это оптимальный вариант? Да, 100%. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 11:27 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Kruchinin Pahan wrote: > Планировщик решил, что правильнее будет индекс не использовать. > > > Возможно проблема в SELECT * > Перечислите только те поля, которые действительно вам необходимы для > суммирования. А это на скорость не повлияет. Таблица всё равно будет читаться. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 11:28 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > db3=> explain select * from internet.trafic_20080901 order by client_id; > QUERY PLAN > ----------------------------------------------------------------------------------- > Sort (cost=*23744033*.*47*..*23944644*.*35* rows=*80244352* width=*43*) > Sort Key: client_id > -> Seq Scan on trafic_20080901 (cost=*0*.*00*..*1552201*.*52* rows=*80244352* width=*43*) > (*3* rows) > > > Планировщик решил, что правильнее будет индекс не использовать. Ой, я это просмотрел. Нет, надо его ЗАСТАВИТЬ использовать индекс и не сортировать данные. Иначе - будет труба. Сортировать такой массив данных очень сложно. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 11:29 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > Даже если одно поле выбрать - все равно индекс не используется. Да и не > много толку будет тут от индекса - все равно все данные загружать. Использование индекса даст возможность не сортировать таблицу. Она у тебя большая. А если ты заставишь сканировать индекс, то, поскольку индекс упорядочен, серверу не придётся сортировать таблицу. Оптимизатор вполне оправдано не берёт индекс, потому что сканировать без индекса конечно же быстрее. Но сортировать дольше. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 11:31 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MasterZiv Использование индекса даст возможность не сортировать таблицу. Она у тебя большая. А если ты заставишь сканировать индекс, то, поскольку индекс упорядочен, серверу не придётся сортировать таблицу. Оптимизатор вполне оправдано не берёт индекс, потому что сканировать без индекса конечно же быстрее. Но сортировать дольше. Posted via ActualForum NNTP Server 1.4 Согласен. Туплю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 11:59 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
А еще быстрее, не использовать индекс и не сортировать данные, выполнять full scan, обрабатывать данные кусками. Файлы открывать по необходимости, а закрывать после завершения всех операций. При поступлении очередной записи записывать ее в нужный файловый поток. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 12:12 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MySQLCraft wrote: > А еще быстрее, не использовать индекс и не сортировать данные, выполнять > full scan, обрабатывать данные кусками. Файлы открывать по > необходимости, а закрывать после завершения всех операций. При > поступлении очередной записи записывать ее в нужный файловый поток. Я бы так и посоветовал бы, если бы не количество групп: "Из этой таблицы нужно взять трафик для каждого client_id и поместить его в свой файл. client_id имеет около 16000 различных значений." 16000 - многовато. В некоторых ОС даже столько файловых дескрипторов не открыть. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 12:36 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MasterZiv Скрябин Дмитрий wrote: > MasterZiv, в этом случае все данные будут в память загружаться всей > кучей, все 6 гигабайт. А ты можешь как-то обработать данные, не читая их в память ? Posted via ActualForum NNTP Server 1.4 Вот, оказывается, могу :) Не читая их разом. Совсем не подумал про курсоры - спасибо Kruchinin Pahan! Так и сделаю. Была трудность как раз в том, чтобы по минимуму нагружать базу и использовать меньше оперативной памяти в процессе работы с этой таблицей. курсоры как раз подходят Открыть 16000 файлов конечно не получится, думаю разбить все данные сначала на 100 файлов (по диапазонам client_id), потом каждый файл еще на 100, тогда в конечном итоге будет в каждом файле не более 100 разных client_id. Там уже каждый файл можно разложить на требуемые файлы. 100 дескрипторов система спокойно потянет :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 13:20 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин ДмитрийMasterZiv, в этом случае все данные будут в память загружаться всей кучей, все 6 гигабайт. Думаешь, это оптимальный вариант? Код: plaintext 1. 2. 3. 4. 5. 6. Планировщик решил, что правильнее будет индекс не использовать.сделайте set enable_seqscan to off; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 13:40 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MasterZiv MySQLCraft wrote: > А еще быстрее, не использовать индекс и не сортировать данные, выполнять > full scan, обрабатывать данные кусками. Файлы открывать по > необходимости, а закрывать после завершения всех операций. При > поступлении очередной записи записывать ее в нужный файловый поток. Я бы так и посоветовал бы, если бы не количество групп: "Из этой таблицы нужно взять трафик для каждого client_id и поместить его в свой файл. client_id имеет около 16000 различных значений." 16000 - многовато. В некоторых ОС даже столько файловых дескрипторов не открыть. Posted via ActualForum NNTP Server 1.4 Буферизовать массивы в оперативной памяти и периодически скидывать на диск, открывая столько файлов, сколько потянет ОС. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 14:24 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Но лучше, открывать только один файл, чтобы не было конкуренции между потоками при записи. Короче. Второй поток, получает порции данных от SQL сервера и сортирует их по 16000 массивам. Второй поток обходит по очереди не пустые массивы, забирает оттуда данные и обнуляет текущий массив, открывает соответствующий файл, пишет, закрывает файл. Периодичность обхода зависит от ограничений оперативки и субъективных критериев. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 14:36 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
очепятка "Короче. Первый поток"... )))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 14:38 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > Вот, оказывается, могу :) Не читая их разом. Совсем не подумал про > курсоры - спасибо Kruchinin Pahan! Так и сделаю. Ты думаешь, что курсоры не тянут куски таблицы в память ? Ты ошибаешься, курсор - ровно такой же запрос, как и все остальное. > Открыть 16000 файлов конечно не получится, думаю разбить все данные > сначала на 100 файлов (по диапазонам client_id), потом каждый файл еще > на 100, тогда в конечном итоге будет в каждом файле не более 100 разных > client_id. Там уже каждый файл можно разложить на требуемые файлы. 100 > дескрипторов система спокойно потянет :) Увеличишь только свою работу внесколько раз. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 15:26 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MySQLCraft wrote: > Буферизовать массивы в оперативной памяти и периодически скидывать на > диск, открывая столько файлов, сколько потянет ОС. а если не влезет ? Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 15:27 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
авторТы думаешь, что курсоры не тянут куски таблицы в память ? Ты ошибаешься, курсор - ровно такой же запрос, как и все остальное. Конечно тянут - но не все 6 гиг сразу, а частями. поэтому в единицу времени скрипт требует не так много памяти. MySQLCraft, спасибо, попробую оба варианта и сравню скорость :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 15:54 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
а SQL-комманду COPY вы не рассматривали? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 17:10 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
Скрябин Дмитрий wrote: > Конечно тянут - но не все 6 гиг сразу, а частями. поэтому в единицу > времени скрипт требует не так много памяти. Так и запрос тебе все 6 гигов сразу не вытащит. Точно так же кусками и будет подтаскивать. На самом деле курсоры сами используются внутри сервера, когда вы запрос выполняете. Это ровно то же самое. вы бежите fetch-ем по строкам, это и есть курсор. > MySQLCraft, спасибо, попробую оба варианта и сравню скорость :) Бессмысленно пробовать два варианта. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2008, 18:30 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
как вариант данные в таблицу подгружать и обрабатывать порциями client_id разбить на группы group_id и партицировать эти группы .. или вовсе разнести в разные таблицы (если позволяет устройство загрузки трафика) выгребать вашим 1-м вариантом несколькими потоками (по идее время select должно значительно уменьшиться, количество запросов в единицу времени возрасти) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2008, 00:12 |
|
||
|
Получение данных из большой таблицы
|
|||
|---|---|---|---|
|
#18+
MasterZiv Так и запрос тебе все 6 гигов сразу не вытащит. Точно так же кусками и будет подтаскивать. На самом деле курсоры сами используются внутри сервера, когда вы запрос выполняете. Это ровно то же самое. вы бежите fetch-ем по строкам, это и есть курсор. На самом деле это не так. Точнее не совсем так, о чем нам и говорит первый абзац в разделе "38.7. Cursors" в документации. Я написал 2 тестовых скрипта, первый тянет данные одним запросом, второй - через курсоры. Второй использует в разы меньше памяти. Если интересует - могу выложить текст скриптов, сами убетитесь или опровергните мое утверждение. Sishnikov, COPY TO рассматривал, но не остановился на нем. php копирует команду только в массив. А копирование в файл во-первых, требует прав postgres, во-вторых, это то же, что и дамп таблицы - проще наверно сделать дамп, если решу работать с текстовым файлом. Степан Н., к сожалению, трафик сейчас можно загружать только в одну таблицу :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2008, 11:34 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=35601267&tid=2003953]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
57ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
63ms |
get tp. blocked users: |
2ms |
| others: | 246ms |
| total: | 407ms |

| 0 / 0 |
