|
|
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B., В индексе Код: plsql 1. В запросе Код: plsql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2016, 16:21 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
SYЕсли таблице дан элиас то в хинте необходимо указывать его а не имя таблицы: Исправил. nimadВ индексе Код: plsql 1. Я почему-то считал, что like регистронезависимый. Исправил, указал upper(CA.VALUE) like upper(:address). План поменялся: Код: 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. 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. Даже INDEX RANGE SCAN для CUSTOMER_CONTACT_VAL_IDX появился. Но запрос по прежнему отрабатывает очень долго. Сейчас поэкспериментирую, мне кажется, что дальше я уже разберусь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2016, 17:00 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
SYЕсли таблице дан элиас то в хинте необходимо указывать его а не имя таблицы: Странно, стало намного хуже. Без хинтов запрос выполняется полторы минуты, с хинтами за полчаса не завершился. Оставил только USE_NL(S B R T), он вроде бы дает положительный эффект. А LEADING и INDEX убрал. В LEADING определяется порядок соединений и по идее LEADING(S B R) должен помогать, но видимо я неправильно понимаю идею. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2016, 18:04 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Чем дальше, тем меньше понимаю. Есть запрос, выполняемый веб-приложением (скриптом на PHP). Запрос возвращает несколько строк (не более пары десятков). Выполняется очень долго, веб-сервер закрывает скрипт по таймауту. Код: 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. Этот же запрос я сегодня запускал в TOAD — в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды), даже если я изменял некоторые параметры. Затем я этот же запрос запустил в SQL*Plus, предварительно задав параметры (такие же как на сайте и в TOAD): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. С сайта запрос по прежнему выполнялся очень долго (точнее его прерывал сервер по таймауту). Сейчас решил снова проверить, запустил его в SQL*Plus — и он выполняется уже почти 10 минут. Запустил его же в TOAD, с теми же параметрами — запрос выполнился за 31 секунду. Повторные запуски — около 400мс. Остановил запрос в SQL*Plus (прошло более 10 минут, он так и не завершился). Запустил его еще раз, прошло уже минуты четыре, а он так и не завершился. Почему в TOAD запрос выполняется быстро? Даже если изменять параметры (:ip или :address), время выполнения не превышает десятка секунд. Почему в SQL*Plus днем он выполнялся быстро, а сейчас долго? SQL*Plus один и тот же, на одной и той же машине (она же сервер СУБД), никаких настроек или окружение среды я не изменял (да и не умею). Почему из PHP (используется библиотека OCI) запрос выполняется долго? В PHP я первоначально использовал хинт RESULT_CACHE, но я пробовал его убирать, ничего не менялось. Вот текущий план из TOAD: Код: 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. 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. С SQL*Plus план срисовать не смог, из-за переноса строк он совершенно нечитаем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2016, 22:47 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B.С SQL*Plus план срисовать не смог, из-за переноса строк он совершенно нечитаем. А что SET LINESIZE отменили? Начни с проcтого. Просмoтри LEFT JOIN. Какой смысл в аутер джойнах типа: Код: plsql 1. 2. Когда в WHERE стоит: Код: plsql 1. 2. Или: Код: plsql 1. 2. Когда в WHERE стоит: Код: plsql 1. 2. Зачем два раза джойн с SERVICES? Почему бы не: Код: 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. Да и "в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды)" - данные поле первого выполнения остаются в buffer cache. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2016, 23:36 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
SYКакой смысл в аутер джойнах типа: Код: plsql 1. 2. Это в первом запросе (до union), с ним вообще никаких проблем нет. SQL формируется динамически и мне удобнее, когда тело запроса постоянное и я только добавляю ограничения в WHERE. Во втором запросе (после union) от внешних соединений попробую избавиться. SYЗачем два раза джойн с SERVICES? Почему бы не: Смысл в SERVICES.TYPE_ID=14. Записи в таблице RADACCT формируются только из SERVICES.TYPE_ID=14. Но записи в таблице BM_SERVICE_MONEY могут быть для любого SERVICES.TYPE_ID. И SERVICES.TYPE_ID!=14 гораздо больше, чем SERVICES.TYPE_ID=14. Я таким образом хотел упростить наиболее "тяжелое" соединение самых больших таблиц RADACCT и BM_SERVICE_MONEY. Попробую убрать внутреннее соединение с SERVICES, возможно оптимизатор Oracle лучше меня с этим разберется. SYДа и "в первый раз он выполнялся около полутора минут, в следующие разы отрабатывал быстро (секунды)" - данные поле первого выполнения остаются в buffer cache. Про кеширование после первого выполнения я предполагал. Возможно что и план запроса кешируется. Но все равно мне непонятно, почему один и тот же запрос с одними и теми же входными параметрами и в одной и той же среде днем и вечером выполняется разное время. Даже в TOAD, вчера днем повторные запросы (после первого запуска) отрабатывали 1-2 секунды, а вечером повторные запросы отрабатывали 400мс? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 09:11 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Убрал left join (заменил на обычный join), убрал из запроса пару таблиц. Выполнил запрос в TOAD, запрос вернул около десятка строк, в первый раз выполнялся 600мс, в следующие разы выполнялся около 400мс. Запустил этот же запрос в SQL*Plus, запрос выполнялся более 10 минут, затем я его прервал. Затем попробовал запустить запрос в TOAD — и он висит уже более 5 минут. Это может быть из-за блокировок? Запросы из этой темы блокировок не показывают. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 10:39 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Всем большое спасибо за советы, вроде бы удалось добиться быстрой работы. Второй подзапрос (после union) теперь выглядит так: Код: 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. В TOAD этот запрос выполняется достаточно быстро, в SQL*Plus тоже. План выглядит так: Код: 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. 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. Но из PHP-скрипта этот запрос по прежнему выполняется долго. Как можно выяснить, в чем причина? Различные настройки окружения и сессии? И как убедиться, что на результаты не влияет кеширование? Я выполнял команды: Код: plaintext 1. 2. Можно считать, что это чистый результат, без влияния кеширования? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 11:36 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B., 1. план от client tool не зависит. 2. оптимайзер достаточно умен чтобы проверять CA.CONTACT_DICT_ID = 3 один раз так-что незачем его тестировать : Код: plsql 1. 2. 3. 4. 5. 3. убери хинты и проверь план и время выполнения. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 13:40 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Так хинты выключены (я убрал плюс). Или речь про RESULT_CACHE? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 13:48 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B., Код: plsql 1. 2. 3. 4. 5. Напрашивается добавить поле FRAMEDIPADDRESS к индексу RADACCT_ACCTSTARTTIME_IDX (хотя estimated плану на 100% доверять нельзя). SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 13:53 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Убрал все хинты: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. Кстати, если условие проверки на :address убрать, то PHP-скрипт результаты отображает довольно быстро. А с дополнительной проверкой на :address (в которой задействован индекс) выполняется долго. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 13:58 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
SYНапрашивается добавить поле FRAMEDIPADDRESS к индексу RADACCT_ACCTSTARTTIME_IDX (хотя estimated плану на 100% доверять нельзя). В таблице RADACCT за 100М записей, я бы не хотел добавлять в нее индекс без особой необходимости. Кроме того, если в запросе задается только эта проверка: Код: plsql 1. 2. 3. то запрос выполняется быстро (в том числе в PHP-скрипте). А вот когда я к нему добавляю Код: plsql 1. то он выполняется долго. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:01 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B.Так хинты выключены (я убрал плюс). Или речь про RESULT_CACHE? Не заметил + убран в хинтe NL. А что тут дает RESULT_CACHE? В плане не вижу ни Код: plsql 1. ни: Код: plsql 1. 2. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:04 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Вот план без проверки на :address (только с :ip) Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. SYА что тут дает RESULT_CACHE? Версии: Oracle Database 10g Release 10.2.0.4.0 - 64bit Production PL/SQL Release 10.2.0.4.0 - Production CORE 10.2.0.4.0 Production TNS for Linux: Version 10.2.0.4.0 - Production NLSRTL Version 10.2.0.4.0 - Production Возможно в моей версии этот хинт недоступен или отключен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:08 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B., Я не предлагал новый индекс. Я педлагал добавить поле к существующему. Тогда отпадет необходимость в TABLE ACCESS BY INDEX ROWID. Насчет "А вот когда я к нему добавляю" - зачем добавлять условие CA.CONTACT_DICT_ID = 3 дважды - один раз в ON а торой раз в WHERE? Масло масляное? Контроьный выстрел? SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:09 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B.Возможно в моей версии этот хинт недоступен или отключен. Query result cache появился, если не ошибаюсь, в 11g. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:14 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
SYЯ педлагал добавить поле к существующему. Но в системе часто требуется быстрый доступ по ACCTSTARTTIME (без учета FRAMEDIPADDRESS). Или в этом случае составной индекс тоже будет использоваться? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:18 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B.Но в системе часто требуется быстрый доступ по ACCTSTARTTIME (без учета FRAMEDIPADDRESS). Или в этом случае составной индекс тоже будет использоваться? Будет, разве-что FRAMEDIPADDRESS очень длинноe поле, хотя судя по имени это IP адрес. В любом случае тестировать всeгда надо. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 14:48 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Ок, буду иметь ввиду этот способ, как запасной. А как мне найти причину, почему один и тот же запрос, с одними и теми же параметрами в TOAD выполняется быстро, а в PHP-скрипте долго? Я подсунул в PHP-скрипт explain plan, получил такой результат: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 16:00 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Оказывается дело не совсем в скрипте. В PHP выполняется такой запрос: Код: plsql 1. 2. 3. 4. 5. 6. То есть два запроса, соединенных через union all и отсортированных. В TOAD этот составной запрос выполняется быстро, также как по отдельности запрос1 и запрос2. В PHP-скрипте каждый запрос по отдельности выполняется быстро, даже если он обернут во внешний запрос с сортировкой (то есть select * from (запрос1) order by ...). А вот составной запрос в PHP-скрипте выполняется долго. Из-за чего может быть такое поведение? Вот план составного запроса при выполнении его в PHP-скрипте: Код: 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. 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. В TOAD план точно такой-же (специально сохранял два плана в текстовые файлы и сравнивал). Но в TOAD запрос отрабатывает быстро. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 16:31 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Alibek B.Но в TOAD запрос отрабатывает быстро. Toad выдает на гора первые строки результата, пoсему и может казаться бысто. Ты в Toad'e нажми пимпочку "до упора", вот тогда и узнаешь полное время всех fetch'ей. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 17:46 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Конкретно в последнем запросе возвращалось около десятка строк, так что дело точно не в этом (TOAD загружает по 500 строк). Ну и в случае PHP-скрипта запрос у меня выполняется дважды — первый раз select count(*) from <sql> (чтобы посчитать число строк), второй раз select *, rn from (select *, rownum rn from <sql> where rownum<=...) where rn>=... (чтобы отобразить выбранную страницу). До второго раза PHP-скрипт не доходит, зависает на select count(*), в котором возвращается только одна строка. Подобные побочные эффекты могут быть из-за union all? Или причина точно не в этом? В крайнем случае я завтра попробую обойтись без union, выполняя запросы отдельно и объединяя результаты уже на клиентской стороне. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.10.2016, 22:12 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Так добaвь COUNT(*) OVER() cnt к select list и первый-же фетч покажет число строк. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.10.2016, 03:19 |
|
||
|
Подскажите, как правильно составить запрос, чтобы эффективно использовались индексы
|
|||
|---|---|---|---|
|
#18+
Спасибо, не знал про такое, так действительно проще. У меня еще такой вопрос. Есть запрос с такой строкой: Код: plsql 1. Запрос возвращает около десятка строк, выполняется моментально. PA.MOMENT проиндексирован. Если сделать так: Код: plsql 1. то запрос выполняется 10-15 секунд, возвращает пару десятков строк. CB.CHANGED не проиндексирован. В таблице PA строк много, в таблице CB строк меньше тысячи. Может быть такая разница из-за того, что CB.CHANGED неиндексирован? Или нужно изучать план выполнения? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.11.2016, 12:27 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39325747&tid=1887083]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
159ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
81ms |
get tp. blocked users: |
1ms |
| others: | 211ms |
| total: | 490ms |

| 0 / 0 |
