Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Выполняется ну очень долго, когда в 3-й таблице десятки тысяч записей. Прекрасно понимаю, что запрос очень тяжелый, но, возможно, есть возможность его изменить/оптимизировать... Подскажите, как. Реляционное вычитание ( а тут именно оно применяется ) -- это очень сложная операция, её сложность - O ( N * M ) , где N и M - кол-во записей в "уменьшаемой" и "вычитаемой" таблицах. СУБД при наличии индексов на поля, по которым происходит вычитание, сделает это за O ( N * log M ) , у вас их два, тогда будет O ( N * log M1 * log M2 ) Если это у вас table3 имеет десятки тыщ записей, то вот у вас и будет десятки тыщ записей обрабатываться, плюс ещё помноженные на два логарифма. Вот и попробуйте прикинуть, сколько это хотя бы в теории должно выполняться, чтение одной записи - считайте порядка 10 msec. Изменить/оптимизировать его нельзя, по одной простой причине - чудес не бывает. Вам остаётся только убедиться, что индексы есть, что они используются, и что они оптимальные. Больше тут ничего не сделаешь. Есть два пути для обдумывания, которые мне приходят сходу на ум: (как всегда) - денормализация, т.е. на этапе записи данных вычисление этой разницы и сохранение где-то в предвычисленном состоянии. На этапе вставки как правило одна или несколько записей обрабатываются, так что время будет размазано по всем вставкам. тексты - не самые лучшие поля для индексирования, возможно, можно создать словарь текстов, и вычитание проводить по идентификаторам слов. Оно по идее будет немного (незначительно) быстрее, но если у вас большие реально объёмы данных, этот выигрыш может накапливаться и давать ощутимую пользу. Вроде бы у вас все эти поля уникальные, тогда по идее они 1:1 соотносятся с первичным ключём и можно просто вычитать по нему, только надо чтобы идентификаторы были в одном пространстве ключей. Больше что-то придумать трудно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 18:27 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
OFFTOPIC: DAISER, для ускорения этих запросов надо избавиться от HashJoin по t1 и от MergeJoin по t2 в пользу NestedLoop +1. NLJ тут рулит фореве, поскольку ему надо ТОЛЬКО С ПЕРВОЙ ЗАПИСЬЮ сджойниться или не сджойниться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 18:30 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatвозможно, медленно работает поиск по индексу table1_field1_key из-за того, что вследствии update и delete накопилось много устаревших версий строк в таблице или индексе. что значить "медленно" ? Всё равно log N. ну сколько там этих устаревших записей? ну 10 процентов. Это - капля в море. Так что совет плохой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 18:32 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatпересоздать индекс тоже никак? пересоздам, но позже. когда будет возможность. LeXa NalBatпокажите ещё пожалуйста explain analyze SELECT field1 FROM table3 WHERE not EXISTS (SELECT 1 FROM table1 WHERE field1 = table3.field1); explain analyze SELECT field1 FROM table3 WHERE not EXISTS (SELECT 1 FROM table2 WHERE field1 = table3.field1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on table3 (cost=0.00..1764082.80 rows=10000 width=70) (actual time=16672.434..299867.119 rows=61 loops=1) Filter: (NOT (subplan)) SubPlan -> Index Scan using table1_field1_key on table1 (cost=0.00..88.18 rows=1 width=0) (actual time=14.987..14.987 rows=1 loops=20000) Index Cond: (field1 = $0) Total runtime: 299867.281 ms (6 rows) QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on table3 (cost=0.00..168146.80 rows=10000 width=70) (actual time=138.135..4727.714 rows=19999 loops=1) Filter: (NOT (subplan)) SubPlan -> Index Scan using table2_field1_key on table2 (cost=0.00..8.38 rows=1 width=0) (actual time=0.234..0.234 rows=0 loops=20000) Index Cond: (field1 = $0) Total runtime: 4732.318 ms (6 rows) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 20:08 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruSeq Scan on table3 (actual rows=61) -> Index Scan using table1_field1_key on table1 Seq Scan on table3 (actual rows=19999) -> Index Scan using table2_field1_key on table2видно, что почти все строки из table3 отсутствуют в table2, и лишь 61 строка отсутствует в table1. поэтому надо попытаться заставить постгрес строки из table3 сначала проверять по таблице table1, и лишь затем немногие прошедшие эту проверку проверять по table2. так как времена сканов по индексам table1 и table2 примерно равны соответственно 23 и 1.6 миллисекунды, то это ускорит запрос совсем немного, примерно на 6 процентов. (эх, если бы оказалось наоборот, что много строк не удовлетворяет проверке по table2, которая быстрая.) 1) как изменяются данные в table1 и table2? 2) статистику покажете? тынц MasterZivСУБД при наличии индексов на поля, по которым происходит вычитание, сделает это за O ( N * log M ) , у вас их два, тогда будет O ( N * log M1 * log M2 )O ( N * log M1 ) + O ( N * log M2 ) ? MasterZiv+1. NLJ тут рулит фореве, поскольку ему надо ТОЛЬКО С ПЕРВОЙ ЗАПИСЬЮ сджойниться или не сджойниться.нет, NestedLoop будет быстрее потому, что, в отличие от HashJoin и MergeJoin, не надо будет целиком читать большие таблицы t1 и t2. джоин идет по уникальным полям, поэтому соединение "только с первой записью" будет для любого типа. MasterZivВсё равно log N.о-большое о-большому - рознь. начинается борьба за константы. MasterZivну сколько там этих устаревших записей? ну 10 процентов.однажды на боевой базе заметили замедление. оказалось, что не выполнялся vacuum, а данные при этом обновлялись целиком ежедневно. за месяц три тысячи процентов лишних неберется, а заметили кажется через несколько месяцев. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2008, 10:41 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
фантастика: если закэшировать в памяти стомиллионную таблицу с её индексом, то запрос ускорится на несколько порядков. реальность: надо ускорять чтение с диска таблицы table1 и её индекса. разнесение по разным дискам таблицы и индекса, быстрые диски, ускоряющий рэйд. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2008, 12:06 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatреальность: надо ускорять чтение с диска таблицы table1 и её индекса. разнесение по разным дискам таблицы и индекса, быстрые диски, ускоряющий рэйд. А я это ещё на прошлой странице сказал... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2008, 17:46 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
сервер более чем достойный. много процов, памяти, SCSI райд и т.д. еще дороже возможности взять нет :( думал, тут виртуозы sql что-то в плане оптимизации запроса помогут сделать... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2008, 21:00 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ru... тут виртуозы sql что-то в плане оптимизации запроса помогут сделать... ну почему же, вам вроде осмысленные советы дают: или ускорить чтените таблицы1 (путем частичного загона в кеш или диски быстрее) или де-нормализациа в каком-либо виде, т.е. хранить результат наличия t3.field1 в t2.field1 and t2 field.1 (индех по функции, доп.поле в t3, etc) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2008, 00:26 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
<<путем частичного загона в кеш это как? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2008, 15:08 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
если памяти достаточнo , то повторный запрос выполняется намного быстрее так как таблица оседает в [linux VFS layer] кеше после первого запроса. (см. последний пост LeXa NalBat: планы по кол-ву дисковых операций одинаковы а время исполненния очень сильно отличаестя) у вас база на чем крутится, размера какого и памяти сколько? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 00:16 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
CentOS 5 64bit 8 гигов памяти. вся база - 150 гигов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 01:16 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Попробую объяснить, зачем вообще понадобилось такие вещи городить, и, возможно, посоветуете, как можно решить те же задачи, но по-другому, с целью повышения производительности. Итак, у нас есть некая программа, которой пользуются несколько сотен пользователей. Все данные хранятся в базе постгреса. Упрощенно говоря, каждому пользователю принадлежит множество записей с некоей текстовой информацией. Задача - обеспечение уникальности этой текстовой информации. Существующая сейчас структура базы данных уже является результатом денормализации. Первоначально, все записи всех пользователей хранились в одной огромной таблице. Поддерживать уникальность было просто - всего лишь уникальным ключом по этому текстовому полю. Но, т.к. данные пользователями активно добавляются, чуть менее активно модифицируются (но, не это поле, а другие, второстепенные) и иногда удаляются, то имея одну таблицу имели огромное торможение. Разнесли данные по отдельным таблицам. Каждому пользователю - свою (это те таблицы, которые фигурировали в моих примерах, как table2). Теперь они друг другу не мешают вообще - каждый работает только со своей таблицей. Но, поддерживать уникальность значений названного текстового поля в пределах всей системы по-прежнему надо. Для этого имеем table1, в которой хранятся все те же текстовые данные с уникальным ключом по этому полю. При попытке пользователя добавить новую порцию данных в свою таблицу, сначала убираем из нее (порции) те, которые уже есть в большой table1, а затем - те, которые уже есть в его (пользователя) таблице table2. Что осталось - инсертим по очереди в table1 и table2. Это, как раз тот запрос, который я приводил, и который меня не устраивает по скорости. Сразу скажу, что выполняется он отложенно, и не пользовательскими приложениями, а отдельной одной единственной специальной программой, поэтому concurrency по инсертам нет никакой. Ну, собственно, вопрос в том, можно ли эту задачу решить как-то иначе, чтобы поиметь существенный выигрыш в производительности? Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 10:38 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
нда, просто добавить памяти походу не получиться исходя из дополнительной инфы, я бы сделал примерно следущее: 1. хранить все в одной таблице, которую поделить на несколько партиций (суб-таблиц) при помощи механизма наследования постгреса,чтоб не было одной гигантской таблицы. 2. при добавлении теск-инфы вычислять ее хеш (sha1 наример) в десятичной форме и по этой функции построить уникальный индекс. Проверка по такому индексу не должна давать задержек. Можно также хранить этот хеш в отдельном поле, возможно будет просще чем связыватся с индексами по функции. 3. деление на партиции по пункту 1 наверно надо организовать так чтоб максимально уменьшить время работы с уникальным индексом для текст-инфы, т..е делить надо будет используя ranges по хешу. Еще наверно имеет смысл и юзеров раскидать по партициям, чтобы все данные одного юзера вседа были в одной партиции/суб-таблице. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 12:17 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
как бы не сделал разделение - после этого уже не получится одним запросом кучу записей проверять на уникальность/инсертить. придется по-одному, что уже замедление. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 12:50 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
почему? если таблица разбита по хешу то легко: BEFORE UPDATE/INSERT вычисляешь хеш , далее операция производистья только с суб-таблицей где хранятся записи с кешами в определенном диапазоне. остальные таблици при этом не трогаются. PS: идея с раскидыванием юзер по суб-таблицам не пройдет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:08 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
кстати если таблица разделена с помощью наследования, то вы работаете с одной таблицей. разделение на суб-таблици происходит автоматически. ПС: при предложеннной схеме денормализация особо не нужна ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:12 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruПопробую объяснить, зачем вообще понадобилось такие вещи городить, и, возможно, посоветуете, как можно решить те же задачи, но по-другому, с целью повышения производительности. Итак, у нас есть некая программа, которой пользуются несколько сотен пользователей. Все данные хранятся в базе постгреса. Упрощенно говоря, каждому пользователю принадлежит множество записей с некоей текстовой информацией. Задача - обеспечение уникальности этой текстовой информации. Существующая сейчас структура базы данных уже является результатом денормализации. Первоначально, все записи всех пользователей хранились в одной огромной таблице. Поддерживать уникальность было просто - всего лишь уникальным ключом по этому текстовому полю. Но, т.к. данные пользователями активно добавляются, чуть менее активно модифицируются (но, не это поле, а другие, второстепенные) и иногда удаляются, то имея одну таблицу имели огромное торможение. Разнесли данные по отдельным таблицам. Это - странное решение. Не понятно, зачем разбивать одну таблицу на несколько, никакой прибавки скорости от этого быть не должно. В PG версионность, индексы дают логарифмический поиск, и в общем-то никакой проблемы быть не должно. Ну если конечно у вас не используется сканирование таблиц без индексов напропалую. tier.ru Но, поддерживать уникальность значений названного текстового поля в пределах всей системы по-прежнему надо. Так просто может быть вам эту уникальность бизнес-логикой поддерживать ? Хранить какие-то пулы идентификаторов, и выдавать их пользователям. Ну не знаю, чего тут придумать, я в общем-то ничего так толком и не понял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:18 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
1. хранить все в одной таблице, которую поделить на несколько партиций (суб-таблиц) при помощи механизма наследования постгреса,чтоб не было одной гигантской таблицы. Чем вам большая таблица-то всем мешает ? А ? 2. при добавлении теск-инфы вычислять ее хеш (sha1 наример) в десятичной форме и по этой функции построить уникальный индекс. Проверка по такому индексу не должна давать задержек. Можно также хранить этот хеш в отдельном поле, возможно будет просще чем связыватся с индексами по функции. Уникальный индекс по хэшу значения не даст уникальности самого значения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:20 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Konstantin~почему? BEFORE UPDATE/INSERT вычисляешь хеш , далее операция производистья только с суб-таблицей где хранятся записи с кешами в определенном диапазоне. остальные таблици при этом не трогаются. . Зачем вам весь этот бред ? Обычный индекс B+ делает в общем-то то же самое. Зачем вам отдельные таблицы ? Что от этого лучше-то будет ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:21 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
MasterZiv Чем вам большая таблица-то всем мешает ? А ? бекапить например не удобно, индекс долго создаётся, еще много всяких неудобств. с таблицами можно работать независимо. (при большом желании можно хоть на разные машины разложить) MasterZiv Уникальный индекс по хэшу значения не даст уникальности самого значения. почему? если хеши одинаковы то и тексты одинаковы. если хеши разные то тексты тоже разные. (имеется ввиду криптографически-стойкий хеш). вообще подход одна-большая-таблица не работает если она действительно большая. тормозит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 13:38 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruПервоначально, все записи всех пользователей хранились в одной огромной таблице. Поддерживать уникальность было просто - всего лишь уникальным ключом по этому текстовому полю. Но, т.к. данные пользователями активно добавляются, чуть менее активно модифицируются (но, не это поле, а другие, второстепенные) и иногда удаляются, то имея одну таблицу имели огромное торможение.не понятно. почему возникали торомоза при конкурентном добавлении данных? и почему сейчас тормозов нет? если большая таблица (в другом виде, как table1) все равно существует, и в нее добаляются данные, и по ней происходит проверка на уникальность. в чем отличие? tier.ruПри попытке пользователя добавить новую порцию данных в свою таблицу, сначала убираем из нее (порции) те, которые уже есть в большой table1, а затем - те, которые уже есть в его (пользователя) таблице table2. Что осталось - инсертим по очереди в table1 и table2.достаточно отфильтровать порцию по таблице table1. последующая фильтрация по table2 ничего не даст, потому что в table2 нет строк, отсутствующих в table1. получается, что таблица table2 вообще не нужна. tier.ruНу, собственно, вопрос в том, можно ли эту задачу решить как-то иначе, чтобы поиметь существенный выигрыш в производительности?ясно решение не видится. при выборке по индексу постгрес читает и индекс, и таблицу. интересно, при вставке с проверкой на уникальность он читает так же, или только индекс? может ускорила бы пока не реализованная фича allow COPY to report error lines and continue . хотя она будет наверное реализована через savepoint-ы, которые тоже требуют времени. :-( можно разнести table1 по нескольким серверам. стоит ли ради десятиминутного запроса? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 15:20 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Попробуйте построить не уникальный индекс по первым 4, 8 буквам. Чем меньше индекс тем проще его кэшировать в памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 17:30 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
А еще можно создать отдельное поле и преобразовать первые байты в int4 или int8. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2008, 17:33 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
бекапить например не удобно, объём данных в N таблицах по x/N записей такой же, что и в одной по x записей. Так какая разница ? индекс долго создаётся, еще много всяких неудобств. То же самое замечание. Длина сканирования аддитивна. Вы ничего не теряете и не приобретаете. Теряется только удобство работы. с таблицами можно работать независимо. Можно. Вопрос - зачем. почему? если хеши разные то тексты тоже разные. Да, это правильно. если хеши одинаковы то и тексты одинаковы. Нет, вот это - неправильно. Если хэши одинаковы, то исходные значения могут быть как одинаковыми, так и разными. (имеется ввиду криптографически-стойкий хеш). Любой. Не важно. вообще подход одна-большая-таблица не работает если она действительно большая. тормозит. Ничего подобного. Ну, еще раз оговорюсь, что ДО ТЕХ ПОР, ПОКА ВАША БД НЕ ОБРАБАТЫВАЕТ ВСЕ ЗАПРОСЫ СКАНИРОВАНИЕМ ТАБЛИЦ, без использования индексов. Но это - случай клинический, и обычно так не бывает, поскольку в сколько-нибудь большой БД это не работает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2008, 17:27 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=35572578&tid=2003996]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
76ms |
get tp. blocked users: |
2ms |
| others: | 209ms |
| total: | 364ms |

| 0 / 0 |
