Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
Не как не пойму правильный механизм работы с индексами. Вобщем суть: Есть некая таблица с кучей полей, одно из которых vg_id - numeric(10,0) >= 0 Создал btree (hash тоже пробовал) индекс по этому полю. Записей в таблице порядка 5 000 000 (для теста, в реальных условиях планирутся примерно 100 лямов). Простой запрос select count(*) from tablename where vg_id = 123 выполняется порядка 8 сек. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2008, 14:25 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
vGhostНе как не пойму правильный механизм работы с индексами. Вобщем суть: Есть некая таблица с кучей полей, одно из которых vg_id - numeric(10,0) >= 0 Создал btree (hash тоже пробовал) индекс по этому полю. Записей в таблице порядка 5 000 000 (для теста, в реальных условиях планирутся примерно 100 лямов). Простой запрос select count(*) from tablename where vg_id = 123 выполняется порядка 8 сек. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Heap (таблица) сканится для получения информации о видимости записи (постгрес - многоверсионная база), так как в индексе нет этой инфы. В 8.4 будет проще, так как будут реализованы карты видимости, которые поднять проще чем таблицу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2008, 18:56 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
Т.е. надо правильно понимать что это особенность PostgreSQL такая, что он не может вычислить количество строк используя один лишь индекс и не сканируя при это сами данные (например найдя в btree индексе текущую позицию, получить в метаданных адрес следующей отличающующейся позиции вычесть адрес текущей и поделить на размер записи получив их количество)? И что "ждать чуда" надо в следующей версии (у мну 8.3.3.)? Или всётаки есть какие то способы разрешения ситуации иными способами. Вообще кто как решает задачу когда нужно получить просто количество записей удовлетворяющих условию, чтоб например построить тот же список страниц например... Или например задача когда у меня в табличке 90 лямов записей, мне нужно получить сумму по некому полю "А" у которых поле vg_id = 123 при всём при том что записей у которых vg_id = 123 менее 0.1% (90к) он это делает аж: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Или может подскажете, возможно есть некая возможность отсортировать исходные данные? Т.е. например в mysql у меня была возможность сделать нечто такое: в 3 часа утра я выполнял следующий запрос: ALTER TABLE tablename ORDER BY vg_id; Это приводило к тому что таблица пересоздавалась на hdd отсортированная по полю vg_id В результате это приводило к тому что все записи находились в исходниках на хдд группами по vg_id. Т.к. все запросы в условиях всегда содержали vg_id + наличие индекса, резко ускоряло работу, т.к. бд скажем весит 15 гиг, но записи с vg_id скажем 123 это всего навсего 0.1% от всех записей, т.е. 15мб. В результате, используя индекс, бд точнчо знала что записи с vg_id =123 на диске находятся только с N по N+15 гиг адреса в файле данных, и читала только часть этого файла, при чём не прерывную часть из 15 мб на диске в которых были записи с vg_id = 123 не читая остальных 14 гигов данных. Возможно ли как то тут реализовать подобное? Или придётся делать таблицу "NEW" которая будет унаследована от родительской и в которую вставлять новые данные, а потом в 3 утра делать INSERT INTO parent (SELECT * FROM child ORDER BY vg_id); после чего TRUNCATE TABLE child; ?? Вообще какие есть методы работы с большими объёмами данных? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2008, 23:21 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
vGhost, посмотрите в сторону "cluster table...." http://www.postgresql.org/docs/8.3/static/sql-cluster.html Удачи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2008, 23:54 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
2 vGhost : медленный count - это особенность postgresql, с ней можно только смириться. если запросы на count одни и те же - можно завести таблицу с заранее подсчитанными значениями и модифицировать её триггерами при добавлении/удалении записей. 2 Oleg Bartunov : гхм... а н приведёт ли это к обратному эффекту - на таблицах, где практически нет "лишних" версий (то есть невелика доля запросов на delete/update относительно запросов на insert) добавление карты видимости заставит postgres делать лишний seek на реальном select? (индекс - карта - данные). или карта маленькая и подразумевается, что она всегда лежит в кэше? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2008, 23:57 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddie2 vGhost : медленный count - это особенность postgresql, с ней можно только смириться. если запросы на count одни и те же - можно завести таблицу с заранее подсчитанными значениями и модифицировать её триггерами при добавлении/удалении записей. 2 Oleg Bartunov : гхм... а н приведёт ли это к обратному эффекту - на таблицах, где практически нет "лишних" версий (то есть невелика доля запросов на delete/update относительно запросов на insert) добавление карты видимости заставит postgres делать лишний seek на реальном select? (индекс - карта - данные). или карта маленькая и подразумевается, что она всегда лежит в кэше? Позволю себе ответить за Олега - нет, к обратному эффекту, относительно текущей ситуации, не приведёт. Да, новая карта будет очень маленькой и подразумевается, что будет поднятой в память. Всё это подробно, с примерами и по-русски расписано тут . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.11.2008, 02:44 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
ничего там не написано ;) Что ещё? Чтобы сделать это Haikki пришлось реализовать так называемые "дополнительные отношения" ("Relation forks"). И это важно, потому что (насколько я понимаю, если я понял не правильно, пожалуйста, поправьте меня) они могут (и наверняка будут) использоваться для хранения "карт видимости" ("visibility maps"), которые сделают vacuum более быстрым (и возможно повлияют на индексные сканирования, но это только моя догадка). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.11.2008, 11:03 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddie медленный count - это особенность postgresql, с ней можно только смириться. если запросы на count одни и те же - можно завести таблицу с заранее подсчитанными значениями и модифицировать её триггерами при добавлении/удалении записей. Ыхх :( Жаль, ну да ладно, это я ещё могу обойти, хотябы тем же триггером и отдельной таблицей, к сожалению это не единственная проблема. Я там второй раз выше не правильный запрос привёл, не то скопипастил, изначально планировалось: EXPLAIN ANALYZE SELECT sum(in) FROM tablename where vg_id = 123; Но результат вобщем то получается тот же (173185.578 ms). К сожалению полей которые будут участвовать в подсчёте несколько и вариантов как самих считаемых полей, так и дополнительных условий к vg_id будет тоже много разных, так что триггер при инсерт и апдейт тут не поможет. :( Но у меня "родилась" ещё одна интересная идея, не знаю как оно поведёт себя на практике, пока не экспериментировал, попробую на выходных, а то и так уже дыру в винте протёр экспериментами, но суть её заключается в следующем: В таблице порядка 16 полей (некоторые переменной длины!), но условия выборки всегда будут затрагивать только 4 из них. Остальные будут "выбираться/считаться" и т.д. А ещё как известно первичный ключ в любой бд работает очень быстро. Следовательно разделив таблицу на 2, в одной 4 поля по которым будет происходить выборка + ключевое поле, а во второй ключевое поле для связи с первой и все остальные "большие" поля. Тем самым уменьшу размер читаемых базой файлов по которым происходит логическая выборка, и через left join соединю их в запросе. В результате запрос будет в условии по первой табличке в которой запись будет фиксированной длины, и которая будет сравнительно маленькая, после чего имея только нужные точные уникальные ID по уникальному ключу она при обработке LEFT JOIN вытащит данные из второй таблицы. Что должно в теории работать очень быстро. Особенно если это связать с предложенной KRED'ом кластеризацией. И сегментированием: где-то-в-инетеСегментирование данных можно организовать с помощью наследования (TABLE INHERITANCE) и CE (CONSTRAINT EXCLUSION). Идея состоит в том, чтобы иметь родительскую таблицу (класс), которая определяет основной набор атрибутов и таблицы, которые наследуют структуру родительской таблицы, но имеющие определенные ограничения на параметр, по которому проводится сегментирование. Механизм наследования в PostgreSQL обеспечивает выполнение запроса по всем таблицам автоматически, при этом наличие CE позволяет просматривать только те таблицы, которые удовлетворяют условию на параметр. Типичная ситуация, когда сегментирование идет по времени, например, для хранение журналов веб-серверов. ---------- :) KRED посмотрите в сторону "cluster table...." http://www.postgresql.org/docs/8.3/static/sql-cluster.html Удачи. Спасибо, очень помогло :) Время выполнения основных запросов упало до менее 1 сек. Вот только есть одно "но", по той ссылке в подзаголовке "Note" написано что эта кластеризация может очень долго выполняться на больших таблицах, а также если делать её в "вакууме" что планёр может не оптимально это делать, и что порой лучше бывает делать её самому путём "INSERT FROM SELECT" с сортировкой по нужному полю. Если есть у кого опыт в данном вопросе очень хотелось бы выслушать опытных людей. А также я пока не нашёл можно ли каким нибудь образом, не применяя полного копирования данных во временные таблицы, сделать кластеризацию не по индексу в текущей таблице, а скажем у меня 2 связанные таблички по ключам, используя индекс во второй по какому то полю отсортировать данные в них обоих. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2008, 19:24 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
в общем случае join существенно медленнее, чем выборка из одной таблицы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2008, 20:26 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddieничего там не написано ;) Что ещё? Чтобы сделать это Haikki пришлось реализовать так называемые "дополнительные отношения" ("Relation forks"). И это важно, потому что (насколько я понимаю, если я понял не правильно, пожалуйста, поправьте меня) они могут (и наверняка будут) использоваться для хранения "карт видимости" ("visibility maps"), которые сделают vacuum более быстрым (и возможно повлияют на индексные сканирования, но это только моя догадка). -rw------- 1 pgdba pgdba 409600000 2008-10-04 13:05 /home/pgdba/data/base/16385/16408 -rw------- 1 pgdba pgdba 122880 2008-10-04 13:05 /home/pgdba/data/base/16385/16408_1 122880/409600000 для 100000 записей И что случится, если я сделаю update 50% записей? # update x set dummy_text = repeat('_test_', 500) where id <= 50000; UPDATE 50000 # \! ls -l $PGDATA/base/16385/16408* -rw------- 1 pgdba pgdba 614400000 2008-10-04 13:09 /home/pgdba/data/base/16385/16408 -rw------- 1 pgdba pgdba 172032 2008-10-04 13:08 /home/pgdba/data/base/16385/16408_1 Это говорит, что излишек данных на диске составляет около 0.03%, что является незначительным. Что не так? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2008, 22:27 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
gray hemp, статья вообще-то про изменения в fsm, кто сказал, что в этих 0.03% сидят "visibility maps"? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2008, 23:46 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddie, Возможно вы правы, что в статье нет чёткого указания на то, что VM будет храниться в "дополнительных отношениях", но, почему-то у меня не возникает сомнений по этому поводу. Думаю, если поискать в списках рассылки, то можно будет найти подтверждение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 01:19 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddie, Кстати, вот и подтверждение http://archives.postgresql.org/pgsql-hackers/2008-10/msg01306.php ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 01:31 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
gray hempСпасибо, очень помогло :) Время выполнения основных запросов упало до менее 1 сек. Вот только есть одно "но", по той ссылке в подзаголовке "Note" написано что эта кластеризация может очень долго выполняться на больших таблицах, а также если делать её в "вакууме" что планёр может не оптимально это делать, и что порой лучше бывает делать её самому путём "INSERT FROM SELECT" с сортировкой по нужному полю. Если есть у кого опыт в данном вопросе очень хотелось бы выслушать опытных людей. А также я пока не нашёл можно ли каким нибудь образом, не применяя полного копирования данных во временные таблицы, сделать кластеризацию не по индексу в текущей таблице, а скажем у меня 2 связанные таблички по ключам, используя индекс во второй по какому то полю отсортировать данные в них обоих. Как вариант предложу прикрутит сюда ещо и партиционирование ... новые данные заливаеш в новые партиции после чего их "сластеризируеш" , а старые лежат на соседних партициях и не меняются. Это конечно если ты данные в основном добавляеш и не изменяеш их рандомно ... , но как мне кажется ты же какето "логи" анализируеш. Хотя если ты ещо и один из основных поисковых критериев разделиш по партициям то скорость ещо немного увеличится. http://www.postgresql.org/docs/8.3/static/ddl-partitioning.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 12:05 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
KRED Как вариант предложу прикрутит сюда ещо и партиционирование ... новые данные заливаеш в новые партиции после чего их "сластеризируеш" , а старые лежат на соседних партициях и не меняются. Это конечно если ты данные в основном добавляеш и не изменяеш их рандомно ... , но как мне кажется ты же какето "логи" анализируеш. Хотя если ты ещо и один из основных поисковых критериев разделиш по партициям то скорость ещо немного увеличится. http://www.postgresql.org/docs/8.3/static/ddl-partitioning.html Да, вы правы это в каком то смысле "логи", изменяться они правда тоже будут, но будет это один раз в жизни, в течении первых суток, за которым уже можно сделать кластеризацию и партиционирование. На данный момент пока остановился на том что буду сначала складывать всё новое в таблицу "new" (которая тоже будет частью партиции) откуда уже после обработки данные переносить по партициям, которые уже не будут меняться, отсортированные внутри партиции по vg_id, и разделённые по датам (к сожалению по основному критерию vg_id разделить не получится, это хоть и int идентификатор, но "предсказать" его нельзя даже по диапазону, т.к. одних может быть очень много). Пока хочу поэкспериментировать, найти т.н. "золотую середину" в размерах этих частей по дате. Правда про партиционирование я уже читал, только там где я об этом читал, это называли сегментированием, о чём выше я уже писал, но сути это не меняет, всё равно спасибо за совет :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 18:12 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
*** но "предсказать" его нельзя даже по диапазону, т.к. одних может быть очень много, а других очень мало).*** P.S. чёта я не найду кнопки редактирования :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 18:15 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
vGhost*** но "предсказать" его нельзя даже по диапазону, т.к. одних может быть очень много, а других очень мало).*** P.S. чёта я не найду кнопки редактирования :( значит делайте по дате , но учтите что большое количество партиций неочень хорошо действует на здоровье постгресу. пару десятков да ... а пару сотен скорее уже перебор. Я бы сделал табличку текущих данных , которые могут меняться , и табличку партиционированую по месяцам(на крайний случай по неделям) для "архивных данных". После переброски данных в архивную кластеризировал ту партицию что поменял ... или рассмотрел возможность "insert into ... select * from table ORDER BY" Хотя кластеризировать и перестроить индексы для нее самое то ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 19:05 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
KREDзначит делайте по дате , но учтите что большое количество партиций неочень хорошо действует на здоровье постгресу. пару десятков да ... а пару сотен скорее уже перебор. почему? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2008, 22:31 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddieKREDзначит делайте по дате , но учтите что большое количество партиций неочень хорошо действует на здоровье постгресу. пару десятков да ... а пару сотен скорее уже перебор. почему? Тратится время на поиск нужной партиции. Т.е. проверяются все условия формирований партиций, что подтормаживает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.11.2008, 12:21 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
eddieKREDзначит делайте по дате , но учтите что большое количество партиций неочень хорошо действует на здоровье постгресу. пару десятков да ... а пару сотен скорее уже перебор. почему? Поищите в форуме .... , а в двух словах "Andrey Daeron" уже ответил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.11.2008, 13:21 |
|
||
|
Как правильно работать_с/создать индекс?
|
|||
|---|---|---|---|
|
#18+
KREDПоищите в форуметут: http://sql.ru/forum/actualthread.aspx?tid=558070 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2008, 10:27 |
|
||
|
|

start [/forum/topic.php?fid=53&fpage=257&tid=2003842]: |
0ms |
get settings: |
7ms |
get forum list: |
17ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
43ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
56ms |
get tp. blocked users: |
2ms |
| others: | 226ms |
| total: | 371ms |

| 0 / 0 |
