2009-03-12 9 views
6

Я пытаюсь оптимизировать запрос, который использует представление в MySQL 5.1. Кажется, что даже если я выберу 1 столбец из представления, он всегда выполняет полное сканирование таблицы. Это ожидаемое поведение?Всегда ли просмотр MySQL всегда выполняет полное сканирование таблицы?

Представление - это просто SELECT «Все столбцы из этих таблиц - NOT *» для таблиц, указанных в первом запросе ниже.

Это мой вывод для объяснения, когда я выбираю индексированный столбец PromotionID из запроса, который составляет представление. Как вы можете видеть, это сильно отличается от вывода на представлении.

EXPLAIN SELECT pb.PromotionID FROM PromotionBase pb INNER JOIN PromotionCart pct ON pb.PromotionID = pct.PromotionID INNER JOIN PromotionCode pc ON pb.PromotionID = pc.PromotionID WHERE pc.PromotionCode = '5TAFF312C0NT'\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pc 
     type: const 
possible_keys: PRIMARY,fk_pc_pb 
      key: PRIMARY 
     key_len: 302 
      ref: const 
     rows: 1 
     Extra: 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pb 
     type: const 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: const 
     rows: 1 
     Extra: Using index 
*************************** 3. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: pct 
     type: const 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: const 
     rows: 1 
     Extra: Using index 
3 rows in set (0.00 sec) 

Выход, когда я выбираю то же самое, но с точки зрения

EXPLAIN SELECT vpc.PromotionID FROM vw_PromotionCode vpc WHERE vpc.PromotionCode = '5TAFF312C0NT'\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: <derived2> 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 5830 
     Extra: Using where 
*************************** 2. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pcart 
     type: index 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: NULL 
     rows: 33 
     Extra: Using index 
*************************** 3. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pcart.PromotionID 
     rows: 1 
     Extra: 
*************************** 4. row *************************** 
      id: 2 
    select_type: DERIVED 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 5. row *************************** 
      id: 3 
    select_type: UNION 
     table: pp 
     type: index 
possible_keys: PRIMARY 
      key: pp_p 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 6. row *************************** 
      id: 3 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pp.PromotionID 
     rows: 1 
     Extra: 
*************************** 7. row *************************** 
      id: 3 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 8. row *************************** 
      id: 4 
    select_type: UNION 
     table: pcp 
     type: index 
possible_keys: PRIMARY 
      key: pcp_cp 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 9. row *************************** 
      id: 4 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.pcp.PromotionID 
     rows: 1 
     Extra: 
*************************** 10. row *************************** 
      id: 4 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 11. row *************************** 
      id: 5 
    select_type: UNION 
     table: ppc 
     type: index 
possible_keys: PRIMARY 
      key: ppc_pc 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 12. row *************************** 
      id: 5 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.ppc.PromotionID 
     rows: 1 
     Extra: 
*************************** 13. row *************************** 
      id: 5 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 14. row *************************** 
      id: 6 
    select_type: UNION 
     table: ppt 
     type: index 
possible_keys: PRIMARY 
      key: ppt_pt 
     key_len: 4 
      ref: NULL 
     rows: 1 
     Extra: Using index 
*************************** 15. row *************************** 
      id: 6 
    select_type: UNION 
     table: pb 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: readyinteractive.ppt.PromotionID 
     rows: 1 
     Extra: 
*************************** 16. row *************************** 
      id: 6 
    select_type: UNION 
     table: pc 
     type: ref 
possible_keys: fk_pc_pb 
      key: fk_pc_pb 
     key_len: 4 
      ref: readyinteractive.pb.PromotionID 
     rows: 249 
     Extra: Using where 
*************************** 17. row *************************** 
      id: NULL 
    select_type: UNION RESULT 
     table: <union2,3,4,5,6> 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: NULL 
     Extra: 
17 rows in set (0.18 sec) 

ответ

9

Представления в MySQL не индексируется так по своей природе требуют полного сканирования каждый раз, когда они доступны. Вообще говоря, это делает вид действительно полезным только в ситуациях, когда у вас довольно сложный статический запрос, который возвращает небольшой результирующий набор, и вы планируете каждый раз захватывать весь результирующий набор.

Редактирование: Конечно, представления будут использовать индексы в базовых таблицах, чтобы оптимизировать представление (в противном случае они вообще не имели смысла использовать), а потому, что нет индексов в представлении View невозможно для запроса WHERE в Оптимизированном представлении.

Построение индексов для видов было бы дорогостоящим, потому что пока я не пробовал просматривать какие-либо виды, я вполне уверен, что временная таблица построена за кулисами, а затем возвращается результат. Для построения временной таблицы уже достаточно времени, я бы не хотел, чтобы представление также пыталось угадать, какие индексы необходимы. Что вызывает второй пункт, который заключается в том, что MySQL в настоящее время не предлагает метод для указания того, какие индексы использовать для представления, и как он знает, какие поля нужно индексировать? Означает ли это, основываясь на вашем запросе?

Возможно, вы можете использовать Temporary Table, потому что тогда вы можете указать индексы для полей во временной таблице. Однако, по опыту, это имеет тенденцию быть действительно, очень медленным.

Если все это представление содержит SELECT ALL FROM table1, table2, table3; то я должен был бы спросить, почему этот запрос должен быть в представлении вообще? Если по какой-то причине это абсолютно необходимо, вы можете захотеть использовать хранимую процедуру для инкапсуляции запроса, так как тогда вы сможете получить оптимизированную производительность, сохраняя при этом преимущество более простого вызова базы данных для набора результатов.

+0

Здесь говорится http://dev.mysql.com/doc/refman/5.0/ru/view-restrictions.html, что представление будет использовать индексы базовых таблиц. – Alex

+0

Я уверен, что вы правы - запросы на представления MySQL могут использовать индексы из исходных таблиц.У вас просто не может быть указателя на самом представлении и, следовательно, не может иметь один индекс, содержащий столбцы из более чем одной из этих таблиц. – thomasrutter

+0

К сожалению, это не объясняет, почему этот второй запрос так плохо оптимизирован MySQL. Все, о чем я могу думать, это, возможно, то, что точка зрения не совсем совпадает с тем, как она предназначена. Не знаю, хотя. – thomasrutter

3

Я смотрел глубже в него, я пропустил ключевой момент информации :(Мой запрос вида фактически имеет объединение с другой таблицей. Это заставляет представление использовать алгоритм TEMPORARY TABLE вместо алгоритма MERGE .

алгоритм TEMPORARY TABLE не допускает использование индексов в базовых таблицах.

Это кажется ошибка в MySQL и сообщалось еще в 2006 году, но не выглядит, как это было решена в 2009 году http://forums.mysql.com/read.php?100,56681,56681

Похоже, мне просто нужно будет повторно написать запрос как выход r присоединиться.

 Смежные вопросы

  • Нет связанных вопросов^_^