Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Две таблицы. В первой - сотни миллионов записей. Во второй - миллионы. В обоих имеется поле типа text с уникальным индексом по нему. Задача: нужно из третьей таблицы (тоже имеет поле типа text с уникальным индексом) выбрать записи, где значение этого поля не встречается ни в первой, ни во второй таблицах. Я делаю: SELECT field1 FROM table3 WHERE not EXISTS (SELECT 1 FROM table1 WHERE field1 = table3.field1) AND NOT EXISTS (SELECT 1 FROM table2 WHERE field1 = table3.field1) Выполняется ну очень долго, когда в 3-й таблице десятки тысяч записей. Прекрасно понимаю, что запрос очень тяжелый, но, возможно, есть возможность его изменить/оптимизировать... Подскажите, как. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 02:05 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
может OUTER JOIN потом проверка на NULL? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 02:31 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
SELECT field1 FROM table3 t3 left join table1 t1 using(field1) left join table2 t2 using(field1) where not t1.field1 is null and not t2.field1 is null; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 02:37 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
ещё вот так можно: http://www.postgresql.org/docs/current/static/queries-union.html Код: plaintext 1. 2. 3. 4. 5. 6. -- „Истина — это вовсе не то, что можно убедительно доказать, это то, что делает всё проще и понятнее“ — Антуан де Сент-Экзюпери ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 02:58 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Думаю DIASER имел в виду Код: plaintext 1. 2. Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 12:02 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
нет там NULL вообще. абсолютно точно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 12:21 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruнет там NULL вообще. абсолютно точно. Когда LEFT JOIN сделаете -- появятся. И как раз в тех случаях, когда я для table3 нет записи в table1 и/или table2. http://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM PostgreSQL Documentation LEFT OUTER JOIN First, an inner join is performed. Then, for each row in T1 that does not satisfy the join condition with any row in T2, a joined row is added with null values in columns of T2. Thus, the joined table unconditionally has at least one row for each row in T1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 14:34 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
А еще, пожалуста,покжите планы (explain analyze select ...) , и вашего запроса, и тех что посоветовали! Интересно посмотреть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.09.2008, 15:40 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Ни один из советов, к сожалению, не помог ускорить запрос. Все тесты запускал для table3 с 20K записей. Мой вариант выполняется строго ~10 мин. План (уже для table3 со 100 записями): QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on table3 (cost=0.00..9572.40 rows=25 width=83) (actual time=151.129..3649.923 rows=89 loops=1) Filter: ((NOT (subplan)) AND (NOT (subplan))) SubPlan -> Index Scan using table1_field1_key on table1 (cost=0.00..87.28 rows=1 width=0) (actual time=25.057..25.057 rows=0 loops=100) Index Cond: (field1 = $0) -> Index Scan using table2_field1_key on table2 (cost=0.00..8.42 rows=1 width=0) (actual time=11.428..11.428 rows=0 loops=100) Index Cond: (field1 = $0) Total runtime: 3650.167 ms (8 rows) Теперь посоветованные. Итак: select field1 from table3 except ( select field1 from table2 union select field1 from table1 ) это - очевидная чушь. памяти надо занять многие гигабайты, чтобы выполнить подзапрос. все-таки запускал для эксперимента. окончания не дождался за час. плана не будет. перестартанул pg для чистоты эксперимента. Следующий: SELECT field1 FROM table3 t3 left join table1 t1 using(field1) left join table2 t2 using(field1) where t1.field1 is null and t2.field1 is null; Не дождался окончания за 30 мин. обрубил. Но, для меньшего размера (100 записей) table3 работает . привожу план: QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------ Nested Loop Left Join (cost=0.00..5202.47 rows=25 width=83) (actual time=1069.094..13140.841 rows=89 loops=1) Filter: (t1.field1 IS NULL) -> Nested Loop Left Join (cost=0.00..837.76 rows=50 width=83) (actual time=263.194..3885.419 rows=100 loops=1) Filter: (t2.field1 IS NULL) -> Seq Scan on table3 t3 (cost=0.00..3.00 rows=100 width=83) (actual time=0.034..0.215 rows=100 loops=1) -> Index Scan using table2_field1_key on table2 t2 (cost=0.00..8.34 rows=1 width=74) (actual time=38.847..38.847 rows=0 loops=100) Index Cond: (t3.field1 = t2.field1) -> Index Scan using table1_field1_key on table1 t1 (cost=0.00..87.28 rows=1 width=66) (actual time=92.548..92.548 rows=0 loops=100) Index Cond: (t3.field1 = t1.field1) Total runtime: 13141.092 ms (10 rows) Ну что, господа, есть еще идеи, что можно тут сделать? Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2008, 21:30 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Тут оптимизация запросов врядли поможет. Хотелось бы увидеть планы выполения, только без analyze. Analyze -- дело случая, от нагрузки на сервер и прочего зависит. Просто explain покажет самый быстрый запрос. По тем планами, что вы показали, ваш запрос действительно быстрее. Ускорить его врядли получится. Надо менять саму базу. Какие индескы у вас используются? b-tree? Попробуйте создать hash-индесы для table1.field1 и table2.field1. http://www.postgresql.org/docs/current/static/indexes-types.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2008, 04:12 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruВсе тесты запускал для table3 с 20K записей. Мой вариант выполняется строго ~10 мин.покажите explain analyze этого запроса tier.ruПлан (уже для table3 со 100 записями)планы для таблиц гораздо меньшего размера не интересны tier.ruэто - очевидная чушь. памяти надо занять многие гигабайты, чтобы выполнить подзапрос.вы разработчик постгреса? знаете какие данные надо держать в памяти, а какие можно свопить на диск, и т.д.? tier.ruвсе-таки запускал для эксперимента. окончания не дождался за час. плана не будет. ... Не дождался окончания за 30 мин. обрубил.в этом случае показывайте explain без analyze DAISERТут оптимизация запросов врядли поможет.-1 DAISERХотелось бы увидеть планы выполения, только без analyze.просто не читайте данные "(actual ...)", вот и будет explain без analyze ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2008, 10:18 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Собственное исследование: 3 таблицы. table1, table2, table3. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. "table2" и "table3" аналогичной структуры. Все поля в таблицах заполнены. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Запрос автора темы: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Мой запрос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Ёш: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. Funny_Falcon: Код: 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. Создаем hash-индексы Код: plaintext 1. 2. 3. 4. 5. 6. Запрос автора: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Мой запрос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Результаты выполнения других двух запросов тоже не изменились. Так что с индексами я погорячился. Что ещё можно попробовать? P.S.: у меня запрос tier.ru выполнялся 1.5-2.5 сек (50 000 записей в table3). Конфигурация, только не смейтесь, P-III 800MHz/384Mb/OpenSUSE 10.2. PostgreSQL 8.3.4, work_mem = 8MB. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2008, 20:29 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
я чё-то не понял, почему вы hash-индексы по полю id создаете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 10:24 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
DAISERМой запрос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. лучше получить результаты тестов от автора, они могут отличаться от ваших, потому что например таблицы замусорены удаленными строками или статистика не собрана или собрана менее подробно или по другим причинам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 11:09 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Вообще фигня какая-то в тестах DAISER. Почему во всех ваших запросах фигурирует поле-счетчик id, в то время как у меня - текстовое поле field1? \d table1 Table "public.table1" Column | Type | Modifiers --------------+-----------------------------+---------------------------------------------------------- id | integer | not null default nextval('table1_id_seq'::regclass) field1 | text | field2 | text | cdate | timestamp without time zone | default now() field3 | text | flags | integer | default 0 status | smallint | not null default (-10) field4 | text | pr | integer | field5 | integer | default 0 Indexes: "table1_pkey" PRIMARY KEY, btree (id) "table1_field1_key" UNIQUE, btree (field1) "table1_field3_index" UNIQUE, btree (field3) "table1_status_index" btree (status) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 11:46 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
OFFTOPIC: DAISER, для ускорения этих запросов надо избавиться от HashJoin по t1 и от MergeJoin по t2 в пользу NestedLoop DAISERМой запрос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Funny_Falcon: Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 11:52 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ru, почему не показываете explain analyze? LeXa NalBat tier.ruВсе тесты запускал для table3 с 20K записей. Мой вариант выполняется строго ~10 мин.покажите explain analyze этого запроса ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 11:54 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
показал же. чтоб не искали в предыдущих постах, вот ще раз: QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on table3 (cost=0.00..9572.40 rows=25 width=83) (actual time=151.129..3649.923 rows=89 loops=1) Filter: ((NOT (subplan)) AND (NOT (subplan))) SubPlan -> Index Scan using table1_field1_key on table1 (cost=0.00..87.28 rows=1 width=0) (actual time=25.057..25.057 rows=0 loops=100) Index Cond: (field1 = $0) -> Index Scan using table2_field1_key on table2 (cost=0.00..8.42 rows=1 width=0) (actual time=11.428..11.428 rows=0 loops=100) Index Cond: (field1 = $0) Total runtime: 3650.167 ms (8 rows) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 12:00 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ruпоказал же... actual rows=89 ...не то. обещали "20K записей" и "~10 мин". как я писал, "планы для таблиц гораздо меньшего размера не интересны". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 12:04 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
Я не настолько силен в базах данных, но по-моему, это один х. Но, все-таки покажу щас. Подождите. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 12:16 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on table3 (cost=0.00..1928003.20 rows=5000 width=70) (actual time=100781.649..490673.590 rows=61 loops=1) Filter: ((NOT (subplan)) AND (NOT (subplan))) SubPlan -> Index Scan using table1_field1_key on table1 (cost=0.00..87.99 rows=1 width=0) (actual time=22.942..22.942 rows=1 loops=19999) Index Cond: (field1 = $0) -> Index Scan using table2_field1_key on table2 (cost=0.00..8.38 rows=1 width=0) (actual time=1.580..1.580 rows=0 loops=20000) Index Cond: (field1 = $0) Total runtime: 490673.753 ms (8 rows) И теперь, если не трудно, объясните мне, малограмотному, чем вас не устроил план запроса по 100 записям и зачем надо было выполнять его еще по 20K? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 12:42 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ru-> Index Scan using table1_field1_key on table1 (actual time=22.942..22.942 rows=1)кажется, что поиск по индексу работает медленно. попробуйте drop index table1_field1_key, vacuum full table1, create index table1_field1_key. и покажите получившийся explain analyze. tier.ruИ теперь, если не трудно, объясните мне, малограмотному, чем вас не устроил план запроса по 100 записям и зачем надо было выполнять его еще по 20K?в частности для того, чтобы разбираясь с проблемой, щупать её саму, а не тестовый пример. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 12:58 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
vacuum full такой огромной таблицы даже на нашем очень мощном железе занимает дня два. уже пробовал. даже бэкап/рестор всей базы и то быстрее (часов за 6 делается). maintenance_work_mem = 512MB postgresql-8.3.3 а это продакшн-система. так что, неосуществимо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 13:27 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
возможно, медленно работает поиск по индексу table1_field1_key из-за того, что вследствии update и delete накопилось много устаревших версий строк в таблице или индексе. как идет работа с таблицами table1 и table2, строки в них только добавляются или еще и изменяются и удаляются? покажите пожалуйста статистику: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. tier.ruvacuum full такой огромной таблицы даже на нашем очень мощном железе занимает дня два. уже пробовал. даже бэкап/рестор всей базы и то быстрее (часов за 6 делается).пересоздать индекс тоже никак? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 15:27 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
покажите ещё пожалуйста 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); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2008, 15:36 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#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 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
<<не понятно. почему возникали торомоза при конкурентном добавлении данных? я так понимаю, из-за блокировок. кроме того, там не только добавление но и огромное количество select и update идет одновременно. <<и почему сейчас тормозов нет? если большая таблица (в другом виде, как table1) все равно существует, и в нее добаляются <<данные, и по ней происходит проверка на уникальность. в чем отличие? в том, что большая таблица задействована только при инсерте новых данных. а другой работы куча делается. <<достаточно отфильтровать порцию по таблице table1. последующая фильтрация по table2 ничего не даст, потому что в table2 нет <<строк, отсутствующих в table1. получается, что таблица table2 вообще не нужна. да, из моего объяснения можно сделать такой вывод. но, на самом деле, большую я иногда чищу от устаревших данных. а в многочисленных маленьких пользовательских таблицах они могут остаться. и, т.к. данные устаревшие, то вероятность весьма мала, что их кто-то может заинсертить повторно. но, она есть, поэтому и с table2 тоже надо делать проверку на уникальность. ну так какое общее мнение, partitioning мне поможет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.10.2008, 23:44 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
tier.ru<<не понятно. почему возникали торомоза при конкурентном добавлении данных? я так понимаю, из-за блокировок. кроме того, там не только добавление но и огромное количество select и update идет одновременно. Прошу прощения, если чушь скажу, но при чем тут это? Какой у вас "default_transaction_isolation" установлен или какой isolation level в транзации, где select выполняется? update'ы должны в WAL записываться, может с его параметрами поиграться? остаются select. если select частые, то таблица table1 или её часть должны быть в кэше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2008, 23:34 |
|
||
|
помогите оптимизировать запрос
|
|||
|---|---|---|---|
|
#18+
может table1.id и table1.field1 вынести в отдельную таблицу? типа, table4(id int, field1 text), которая связана с table1 по id. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.10.2008, 23:37 |
|
||
|
|

start [/forum/topic.php?all=1&fid=53&tid=2003996]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
41ms |
get topic data: |
8ms |
get forum data: |
4ms |
get page messages: |
97ms |
get tp. blocked users: |
2ms |
| others: | 218ms |
| total: | 399ms |

| 0 / 0 |
