|
|
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
Сервер выполняет много мелких запросов, выполняет быстро. Индексы летают. Но есть один запрос, который выполняется в функции различное время, это зависит от входных данных (переменные взяты в коммент) - от 11 сек до 3 минут. Поломали уже голову, перебирая все возможные варианты ускорения. Решили прибегнуть к помощи нашего любимого SQL.RU Запрос не буду перестраивать, так как на простейших запросах проблем нет - они появляются, когда взаимодействует множество селектов. Итак, выполняем запрос: Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. Получаем: Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. Что первое бросается в глаза - это то, что оптимизатор сильно ошибается в подсчете строк: Код: plsql 1. 2. 3. 4. Пробовал статистику для колонок, но это повлияло на оценку строк совсем незначительно: Код: plsql 1. 2. 3. Перед работой выполнялась команда Код: powershell 1. Железо: Intel D525MUD, DDR3 1Gb PostgreSQL 9.3.1 Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Вот инормация о количестве записей: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Если какие-то детали нужны - отвечу. Дамп прикрепил на всякий случай :) Пробовал в памяти диск создать (добавлял планку на 1Гб), пробовал индексы/таблицы туда разные пихать, прирост небольшой. Сильно помог "Index Only Scan using org_address_org_search". Пробовал org_address объединить с a0, и это дало хороший прирост(около 30%), если строка в a0 - одна; если больше, то объединение замедляется на количество строк в a0 линейно. Пробовал посчитать количество записей перед выполнением большого запроса "limit loc_ocnt", чтобы подсказать оптимизатору, что записей не надо брать много, а надо столько, сколько в лимите сказано - конечно, это немного ускорило запрос, но как то не красиво, да и дальше опять оптимизатор из-за количества не верного выбирает не верную дорожку. У кого есть идеи, поделитесь, пожалуйста. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 23:09:33 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
попробуйте set enable_sort to off. чтобы не вытаскивать целиком 10М строк и группировать их в 700К, лишь для того чтобы выдать 1К. подробную статистику попробуйте собрать по колонкам org_id. кстати, максимально подробная - 10000. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2014, 14:00:52 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
Итак, сначала :) Делаю вакуум с анализом, и два раза запускаю запрос упомянутый выше(на первый ушло 120 сек), получаю план на 45 сек: Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. Код: plsql 1. 2. 3. 4. 5. 6. 7. Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. Выводы: К сожалению, максимально подробная статистика (10000), не помогла - строки оптимизатор так и считает не верно. Только первый запуск стал очень хорошим... Более подробная статистика по полю org_id также эффекта не дала. "set enable_sort to off" повлиял немного на план в одном месте: Hash Join + Sec Scan + Hash -> Merge Join + Index Only Scan + Sort Только выигрыша по времени от этого не произошло :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2014, 21:22:32 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
Для упрощения понимания сократим запрос Код: plsql 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. соберем статистику ALTER STATISTIC 10k Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. EXPLAIN PLAN Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. EXPLAIN PLAN Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. Тоесть limit перестал оказывать влияние после сбора более подробной статистики, а "enable_sort" повлиял только на стоимость: offWindowAgg (cost=20007413672.5220GonWindowAgg (cost=7413672.527.4MИ ошибка при подсчете строк стала значительно меньше, и пропало безумное "200", став 3.5млн вместо 0.7млн - и это уже хорошо! Только для org_address должен использоваться SeqScan для такого количества(SeqScan для этой таблицы около 7-10 сек), а заставить его использоваться не получается. Для этого пробовал перебирать random_page_cost и cpu_tuple_cost. SHOW ALLnamesettingallow_system_table_modsoffapplication_namepgAdmin III - ???????????????????? ????????????????archive_command(disabled)archive_modeoffarchive_timeout0array_nullsonauthentication_timeout1minautovacuumoffautovacuum_analyze_scale_factor0.1autovacuum_analyze_threshold50autovacuum_freeze_max_age200000000autovacuum_max_workers3autovacuum_naptime1minautovacuum_vacuum_cost_delay20msautovacuum_vacuum_cost_limit-1autovacuum_vacuum_scale_factor0.2autovacuum_vacuum_threshold50backslash_quotesafe_encodingbgwriter_delay200msbgwriter_lru_maxpages100bgwriter_lru_multiplier2block_size8192bonjouroffbonjour_namebytea_outputescapecheck_function_bodiesoncheckpoint_completion_target0.9checkpoint_segments32checkpoint_timeout5mincheckpoint_warning30sclient_encodingUNICODEclient_min_messagesnoticecommit_delay0commit_siblings5config_file/home/pgsql/postgresql.confconstraint_exclusionpartitioncpu_index_tuple_cost0.005cpu_operator_cost0.0025cpu_tuple_cost0.1cursor_tuple_fraction0.1data_directory/home/pgsqlDateStyleISO MDYdb_user_namespaceoffdeadlock_timeout1sdebug_assertionsoffdebug_pretty_printondebug_print_parseoffdebug_print_planoffdebug_print_rewrittenoffdefault_statistics_target100default_tablespacedefault_text_search_configpg_catalog.englishdefault_transaction_deferrableoffdefault_transaction_isolationread committeddefault_transaction_read_onlyoffdefault_with_oidsoffdynamic_library_path$libdireffective_cache_size704MBeffective_io_concurrency1enable_bitmapscanonenable_hashaggonenable_hashjoinonenable_indexonlyscanonenable_indexscanonenable_materialonenable_mergejoinonenable_nestlooponenable_seqscanonenable_sortonenable_tidscanonescape_string_warningonevent_sourcePostgreSQLexit_on_erroroffexternal_pid_fileextra_float_digits0from_collapse_limit8fsynconfull_page_writesongeqoongeqo_effort5geqo_generations0geqo_pool_size0geqo_seed0geqo_selection_bias2geqo_threshold12gin_fuzzy_search_limit0hba_file/home/pgsql/pg_hba.confhot_standbyoffhot_standby_feedbackoffident_file/home/pgsql/pg_ident.confignore_checksum_failureoffignore_system_indexesoffinteger_datetimesonIntervalStylepostgresjoin_collapse_limit8krb_caseins_usersoffkrb_server_keyfilekrb_srvnamepostgreslc_collateen_US.UTF-8lc_ctypeen_US.UTF-8lc_messagesen_US.UTF-8lc_monetaryen_US.UTF-8lc_numericen_US.UTF-8lc_timeen_US.UTF-8listen_addresses*lo_compat_privilegesofflocal_preload_librarieslock_timeout0log_autovacuum_min_duration-1log_checkpointsofflog_connectionsofflog_destinationstderrlog_directorypg_loglog_disconnectionsofflog_durationofflog_error_verbositydefaultlog_executor_statsofflog_file_mode0600log_filenamepostgresql-%Y-%m-%d_%H%M%S.loglog_hostnameofflog_line_prefixlog_lock_waitsofflog_min_duration_statement-1log_min_error_statementerrorlog_min_messageswarninglog_parser_statsofflog_planner_statsofflog_rotation_age1dlog_rotation_size10MBlog_statementnonelog_statement_statsofflog_temp_files-1log_timezoneAsia/Yekaterinburglog_truncate_on_rotationofflogging_collectoroffmaintenance_work_mem60MBmax_connections100max_files_per_process1000max_function_args100max_identifier_length63max_index_keys32max_locks_per_transaction64max_pred_locks_per_transaction64max_prepared_transactions0max_stack_depth2MBmax_standby_archive_delay30smax_standby_streaming_delay30smax_wal_senders0password_encryptiononport5432post_auth_delay0pre_auth_delay0quote_all_identifiersoffrandom_page_cost2restart_after_crashonsearch_pathmsn publicsegment_size1GBseq_page_cost1server_encodingUTF8server_version9.3.1server_version_num90301session_replication_roleoriginshared_buffers240MBshared_preload_librariessql_inheritanceonssloffssl_ca_filessl_cert_fileserver.crtssl_ciphersnonessl_crl_filessl_key_fileserver.keyssl_renegotiation_limit512MBstandard_conforming_stringsonstatement_timeout0stats_temp_directorypg_stat_tmpsuperuser_reserved_connections3synchronize_seqscansonsynchronous_commitonsynchronous_standby_namessyslog_facilitylocal0syslog_identpostgrestcp_keepalives_count9tcp_keepalives_idle7200tcp_keepalives_interval75temp_buffers8MBtemp_file_limit-1temp_tablespacesTimeZoneAsia/Yekaterinburgtimezone_abbreviationsDefaulttrace_notifyofftrace_recovery_messageslogtrace_sortofftrack_activitiesontrack_activity_query_size1024track_countsontrack_functionsnonetrack_io_timingofftransaction_deferrableofftransaction_isolationread committedtransaction_read_onlyofftransform_null_equalsoffunix_socket_directories/tmpunix_socket_groupunix_socket_permissions0777update_process_titleonvacuum_cost_delay0vacuum_cost_limit200vacuum_cost_page_dirty20vacuum_cost_page_hit1vacuum_cost_page_miss10vacuum_defer_cleanup_age0vacuum_freeze_min_age50000000vacuum_freeze_table_age150000000wal_block_size8192wal_buffers7MBwal_keep_segments0wal_levelminimalwal_receiver_status_interval10swal_receiver_timeout1minwal_segment_size16MBwal_sender_timeout1minwal_sync_methodfdatasyncwal_writer_delay200mswork_mem50MBxmlbinarybase64xmloptioncontentzero_damaged_pagesoff ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2014, 08:27:11 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
Путем перестановки внутри полного запроса удалось снизить время на 5 секунд: Запрос полный, 28286мс Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. EXPLAIN PLAN полный, 28286мс Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. Встречал в некоторых статьях рекоммендации "против объединения" - OFFSET 0, но эта конструкция на EXPLAIN никак не влияла и на конечное время тоже. Зато помогает LIMIT с заведомо большим числом, чем количество возвращаемых запросом записей - сразу и EXPLAIN поменялся и время уменьшилось. В запросе пропали сортировки! (гиганские) - боритесь с сортировками в запросах! не нужно будет выставлять большой work_mem! У меня данный запрос выполняется одинаково по времени и с work_mem=1MB и с work_mem=100MB. Конечно, Postgres сам увеличивает work_mem, если ему не хватает, но это Варнинг, желательно чтобы это было не часто. Подскажите, пожалуйста, что еще можно попробовать для ускорения, и как провести испытания по применению SeqScan для org_address? Сейчас основное замедление происходит в момент склейки a0 и w3, а также когда работаем с 1100641 строк при подготовке w3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 13:28:10 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
R_Onlyчто еще можно попробовать для ускорения, и как провести испытания по применению SeqScan для org_address? Разные подстройки таких сложных планов не слишком устойчивы. В какой-то момент, типа улучшения работы планировщика или роста таблиц, это _внезапно_ перестанет работать. Выйдет pg 10.0, и вам снова придется долго копать эти жуткие планы. IMHO, самое надежное - выгружать отдельные части во временные таблицы. И оптимизировать просто, и планы устойчивы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 15:14:22 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
tadmin, А как насчет materialized view для этих целей? Все хочу попробовать, руки все чешутся - но никак не доходят. Ибо заняты. Запросы тоже страшные, с упоминанием okved и иже :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 16:59:22 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
Hawkmoon, мат.вью мы пока не используем, хотя есть похожие отчеты и знакомые ключевые слова -) На мой взгляд, для очень сложных запросов, по которым не нужен реалтайм, проще набивать из временных таблиц. У нас это решено так: - для извлечения данных используются уже агрегированные данные в отдельной таблице - она наполняется планаровщиком (cron), который дергает хранимые процедуру По моему опыту, структура pl/pgsql процедуры более наглядна, нежели один многоуровневый запрос. В очень тяжелых случаях планировщик разделяет на отдельные транзакции наполнение промежуточных данных. Для случаев попроще мы используем самодельную процедуру, которая анализирует pg_attribute и из view создает таблицу. В отличие от select into или мат.вью, наша функция понимает, где нужно создать индексы в этой таблице. Поскольку у нас свои domain и довольно строгая нотация в названиях полей, это несложно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 18:06:18 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
tadminРазные подстройки таких сложных планов не слишком устойчивы. В какой-то момент, типа улучшения работы планировщика или роста таблиц, это _внезапно_ перестанет работать. Выйдет pg 10.0, и вам снова придется долго копать эти жуткие планы. IMHO, самое надежное - выгружать отдельные части во временные таблицы. И оптимизировать просто, и планы устойчивы.У нас такой запрос один всего, так-что смена версии нас особо не пугает - чем быстрее он будет выполняться на нашей базе, тем лучше! Новую версию ПО надо, конечно, тестить внимательно, а потом уже выкладывать в продакшн. К тому же чем больше я вижу и изучаю эти планы, тем легче мне будет делать эту работу повторно. Да и в других местах пригодятся эти знания/способности анализа. Да, временная таблица очень хорошо помогла, спасибо за совет , tadmin ! Запрос ускорился примерно на 30%! Так что представляю на суд публики более понятные планы и запросы! Заполняем временную таблицу (источник w3) - 7261мс Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. EXPLAIN Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. Но к сожалению vacuum не делается из функции, а у нас все эти действия выполняются в одном месте - в функции pg/sql. Выводим результат - 13694мс Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. EXPLAIN Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. Здорово, что сейчас оптимизатор почти не ошибается при подсчете строк при union all, и знает, какой план будет быстрее! Материализованные вьюхи нам не подходят, т.к. много входных переменных. Если видите, где можно вставить - подскажите... Пробовал избавиться от сортировки на 50МБ, "set enable_sort to off;": вместо Merge стало Nested и время увеличилось на 5733 мс. Как еще можно повлиять на общее время выполнения запросов? Есть предложения по оптимизации? :) Мне кажется, что "org_address a" склеивается с "org_address r" слишком долго - целых 11 секунд. А в первом запросе присоединение (union all) источника на 0.499мс (2 записи) занимает целых 427мс (попробовал переставить источники местами, план поменялся, время - нет. видимо, производится копирование всех строк обоих источников данных, а не Append) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 13:24:26 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
R_Only <>Далее можно было бы сделать CREATE INDEX tmp_seller_allorg_idx ON tmp_seller_allorg USING btree (z,o); vacuum tmp_seller_allorg; что позволило бы сохранить память и не выполнять операцию сортировки (будет использоваться Index Only Scan и ускорится на 1с) в дальнейшем, но увеличит общее время выполнения на 1с. Конечно, temp_buffers надо было бы также увеличить на размер индекса. Но к сожалению vacuum не делается из функции, а у нас все эти действия выполняются в одном месте - в функции pg/sql. <> зачем вам вакуум в ф-ии ?? Вам (вероятно) нужен ANALYZE (без какого либо "вакуум") - а тот нормально выполняется внутри блока транзакций. Хотя, сразу после создания индекса и он, пожалуй не нужен. ну а если вы времянку используете без многочисленных апдейтов в ней и прочей логики "многократно-доступа-изменения" - то вам достаточно CTE. с теми же параметрами (т.е. SET) транзакции CTE не должен ничем отличаться от времянки, за искючением того, что его можно и на стендбае выполнить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 13:48:09 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
qwwqзачем вам вакуум в ф-ии ?? Вам (вероятно) нужен ANALYZE (без какого либо "вакуум") - а тот нормально выполняется внутри блока транзакций. Хотя, сразу после создания индекса и он, пожалуй не нужен.Одного analyze не хватает(проверено) - index only scan не будет использоваться, т.к. не заполнен bitmap таблицы, а если он не используется, то и индекс не нужен совсем. qwwqну а если вы времянку используете без многочисленных апдейтов в ней и прочей логики "многократно-доступа-изменения" - то вам достаточно CTE.посмотрите предыдущие запросы. там именно CTE. только это замедляло выполнение. qwwqс теми же параметрами (т.е. SET) транзакции CTE не должен ничем отличаться от времянки, за искючением того, что его можно и на стендбае выполнить.тем не менее - отличается, обратите внимание на EXPLAIN полного запроса "EXPLAIN PLAN полный, 28286мс". оптимизатор считает, что w3 вернет 200 строк. как его в этом переубедить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:02:33 |
|
||
|
На пути к идеальному плану
|
|||
|---|---|---|---|
|
#18+
R_Only <>тем не менее - отличается, обратите внимание на EXPLAIN полного запроса "EXPLAIN PLAN полный, 28286мс". оптимизатор считает, что w3 вернет 200 строк. как его в этом переубедить? а можно, я не буду вчитываться ? я только замечу, что странно вы, на поверхностный, cte используете. агрегат - у вас аккурат и не cte, а подзапрос. а cte - это некие (вероятно очень объёмные) фильтры. Что в комбинации со знанием, что cte в постгресе на сегодня - это материализация (а не алиас "вьюхи") - выглядит более чем странно. лично у меня паттерны такие: там где вам надо фильтрануть до группировки - обычно кладёте фильтр в подзапрос (с тем неудобством, что выписывать его надо столько раз, сколько он встретится в), а там, где что-то реально раз и навсегда посчитали (или необходимо материализовать ещё по каким соображениям) -- можно и в cte пихать -- хуже не станет. Это развязывает руки планировщику (нет необходимости материализовывать 100500 записей, получаемых до группировки из фильтров), но добавляет гемора с собственно написанием -- при множественном вхождении одной и той же конструкции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.01.2014, 15:37:00 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=38527127&tid=1998894]: |
0ms |
get settings: |
10ms |
get forum list: |
20ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
212ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
77ms |
get tp. blocked users: |
2ms |
| others: | 223ms |
| total: | 569ms |

| 0 / 0 |
