|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Проверяю работу индексов в Oracle. Для этого генерирую таблицу на сто миллионов записей, с четырьмя колонками A,B,C,D Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
Добавляю индекс по A и C и делаю запрос с фильтрацией по A и C: Код: plsql 1. 2. 3.
Выполняется стабильно за 35 мс. Вот план: Код: 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.
Теперь добавляю индекс по A и D, выполняю тот же запрос и вдруг Oracle переклинивает и он начинает использовать индекс AD (вместо AC) и выполнятся стабильно за 250мс. Код: 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.
Удаляю, все становится нормально, добавляю опять использует AD. В чем может быть дело? Версия oracle: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2019, 16:49 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Nitro_Junkie, Ошибся, не Код: plsql 1.
А: Код: plsql 1.
Собственно в плане это видно. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2019, 16:51 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Nitro_JunkieВ чем может быть дело? Статистику пересоберите после добавления индекса. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2019, 16:57 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
andrey_anonymous, Спасибо вроде помогло, хотя конечно не очевидно, что построение индекса не обновляет его статистику. Но раз уже подняли вопрос с индексами. Такой вопрос, есть таблица с 10млн записей, в которой одна колонка SD заполнена только для 10к значений. По этой колонке есть индекс : Код: 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.
Делаю запрос: Код: plsql 1.
Oracle упорно отказывается использовать этот индекс. Код: 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.
Все что можно уже пересчитал. Может нужно с какими-то хитрыми опциями колонку / индекс создавать? ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 10:46 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Nitro_JunkieВсе что можно уже пересчитал. Может нужно с какими-то хитрыми опциями колонку / индекс создавать? У этого индекса фактор кластеризации 10000. Фактически, для выполнения указанного запроса серверу придется посетить практически все блоки таблицы, но по индексу - так нафига козе баян? ...если бы Вы sd подсчитывали, то индекс был бы к месту. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 11:47 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
andrey_anonymousNitro_JunkieВсе что можно уже пересчитал. Может нужно с какими-то хитрыми опциями колонку / индекс создавать? У этого индекса фактор кластеризации 10000. Фактически, для выполнения указанного запроса серверу придется посетить практически все блоки таблицы, но по индексу - так нафига козе баян? ...если бы Вы sd подсчитывали, то индекс был бы к месту. Просто фокус, что этот запрос выполняется в среднем 350мс. А SELECT /*+ INDEX (s1 shipmentdetail_sd) */ COUNT(DISTINCT data) FROM ShipmentDetail s1 WHERE s1.sd IS NOT NULL В среднем 60мс. А есть какая-то настройка заставить Oracle агрессивнее использовать индексы (а точнее рандомный доступ, типа random_page_cost в Postgres) ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 12:02 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Nitro_JunkieА есть какая-то настройка заставить Oracle агрессивнее использовать индексы optimizer_index_cost_adj Но по факту для особо критичных запросов надо не "заставлять" с риском поломать соседние запросы, а проектировать индексы как часть схемы данных. К примеру, рассмотреть составной индекс (sd, data). ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 12:06 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
andrey_anonymousК примеру, рассмотреть составной индекс (sd, data)."Есть запрос - давай создадим индекс" - смахивает на медвежий совет. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 12:08 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Elicandrey_anonymousК примеру, рассмотреть составной индекс (sd, data)."Есть запрос - давай создадим индекс" - смахивает на медвежий совет. А если не выдергивать из контекста? ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 12:14 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
andrey_anonymousElicпропущено... "Есть запрос - давай создадим индекс" - смахивает на медвежий совет. А если не выдергивать из контекста?Всё именно в контексте. Где хватает подсказки. А ты действуешь по-хайнлайновски: "Вижу запрос - готов индексировать". andrey_anonymousФактически, для выполнения указанного запроса серверу придется посетить практически все блоки таблицы, но по индексуТы странно рассуждаешь. 0,1% - это очень удобно для индексного доступа пр любом CF. Тем более, что пример явно неправдоподобно неудачный: data не заполнен при потенциальной длине 2000. А при заполненности вред от от твоего индекса покроет пользу как бык овцу. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 12:37 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Elicandrey_anonymousА если не выдергивать из контекста?Всё именно в контексте. И все-таки сделай усилие, прочитай целиком пост, из которого ты выдернул тему про составной индекс - там всего две строчки. ElicА ты действуешь Я же не вменяю тебе какой-либо образ действий, верно? Буду признателен за взаимность. ElicТы странно рассуждаешь. 0,1% - это очень удобно для индексного доступа пр любом CF. Не при любом CF и не с любым предикатом. У ТС короткие строки, причем проиндексированные строки так распределены, что для их отбора с указанным ТС предикатом придется посетить б о льшую часть блоков. Я отсортировал исходную таблицу ТС относительно sd, фактор кластеризации индекса упал до 3 и индекс начал использоваться. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 13:09 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
andrey_anonymous, Я уменьшил количество не null sd до 100 тоже начал использоваться. Меня на самом деле интересовала принципиальная возможность использования этого индекса (правда в другом запросе), так что я получил ответ на свой вопрос. Но раз пошла такая пьянка, есть еще интересная вещь. Кроме таблицы shipmentDetail сверху есть еще таблица product (с товарами). Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
И индекс по product, shipment в shipmentDetail: Код: plsql 1.
Делаю вот такой запрос: Код: plsql 1.
Получаю план Код: 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.
Все хорошо. Oracle использует индекс и что самое главное догадывается вставить FIRST ROW. Теперь делаю тот же запрос с Predicate push down Код: plsql 1. 2. 3.
Код: 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.
В плане никакого FIRST ROW (должен быть над INDEX) нет. Ну и хер бы с ним, записей не много. Делаем с большим количеством записей (просто убирая фильтр по имени). Код: plsql 1. 2. 3.
Код: 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.
Опять никакого FIRST ROW и запрос выполняется почти 3 секунды. Переписываем запрос с явным rownum = 1 (SUM пришлось добавить, не в курсе как SQL Developer заставить не fetch'ить запросы) Код: plsql 1.
Получаю нормальный план: Код: 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.
То есть с FIRST ROW (в данном случае COUNT STOPKEY, но суть та же) и временем выполнения 400 мс в 10 раз меньше. Причем те же яйца в MS SQL. Это что за фигня? Почему когда предикат равен значению оптимизатор понимает что надо взять одну запись, а при join predicate push down нет. Там же по идее одинаковые оптимизаторы должны быть. И здесь тяжело объяснить это cost'ами или неправильной статистикой, потому как FIRST ROW нужно по идее в любом случае вставлять. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 14:32 |
|
Неправильное использование индекса по двум колонкам
|
|||
---|---|---|---|
#18+
Nitro_Junkie, Собственно в предпоследнем случае никакого даже predicate push down'а нет. Что в принципе понятно, так как без FIRST ROW у него очевидно cost выше будет. Но с FIRST ROW план должен был быть приблизительно как в последнем запросе (и он явно был бы дешевле). ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2019, 14:38 |
|
|
start [/forum/topic.php?fid=52&msg=39843389&tid=1882239]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
36ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
others: | 18ms |
total: | 147ms |
0 / 0 |