2013-07-22 7 views
2

У меня есть 2 больших стола, product и product_variants. В настоящее время я использую представление MySQL, поэтому мне нужно это SQL-заявление много раз. Структура базы данных не может быть изменена atm.MySQL Union in View

Продукт:
ID | IsMaster | EAN | Имя | Цена ...

Product_Variants:
ID | PID (FK на Product.ID) | IsMaster | EAN | Имя | Цена ...

Вид my_view содержит отборное, как это:

(SELECT * FROM `product`) UNION (SELECT * FROM `product_variants`) 

Когда я сейчас делаю запрос, как это:

SELECT * FROM my_view WHERE EAN = '11110' 

Это занимает около 0,5 до 1 секунда. Если я хотел бы использовать содержание зрения непосредственно путем добавления where для каждого подзапроса, это супер быстрый (~ 0004 сек):

(SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110') 

Как я могу использовать более быстрый метод в представлении? Мне нужно перейти на функцию MySQL?

ТИА Matt

+0

Можете ли вы получить данные как больше столбцов (объединение), а не больше строк (объединение)? – Bohemian

ответ

1

Вы должны использовать какую-либо команду MySQL, чтобы проанализировать запрос, как использовать EXPLAIN с оператором выбором и проверить таблицы и структуру индекса.

Использование команды

набор профилирование = 1;

затем использовать запрос на выборку Параметром этой команды

показать профили для Query1;

проверить результат, о котором идет речь, сколько времени.

и некоторые другие имп запрос являются

* SHOW CREATE TABLE TBL \ G - двигатель, индексы

  • SHOW TABLE STATUS LIKE 'ТПС' \ G - размеры

  • EXPLAIN SELECT ... \ G - ключи неэффективности

  • SHOW VARIABLES LIKE '% buffer%'; - ca **

+0

Использование профилирования возвращает 0,3 секунды для отправки данных. Что это значит для этого? – frgtv10

+0

В соответствии с моими знаниями время передачи данных в mysql используется во время сканирования таблицы для получения результата.так как вы можете видеть, когда вы делаете первый союз, а затем используете, где близко к результату выборки, то mysql полностью просматривает ваше представление, а затем извлекает результат в соответствии с вашим запросом , а во втором случае, когда вы используете «где» перед «объединением», тогда mysql сканирует меньше результата из-за предварительной фильтрации where where. Для получения дополнительной информации вы можете проверить поток выписки из предложения – developerCK

+0

Вы рекомендуете прекратить использование представления в этом случае, правильно? – frgtv10

2

Вы можете найти эту статью полезной - http://www.mysqlperformanceblog.com/2007/08/12/mysql-view-as-performance-troublemaker/

Основная предпосылка в том, что взгляды MySQL, чтобы помочь с написанием несложных SQL не с оптимизацией кода.

[] VIEW просто расширяется как макро или временной таблицы в этом случае VIEW материализуется для временных таблиц (без индексов!)

Индекс не = медленно выбирать запросы.

+0

Ваш результат: удалить вид? Индекс уже установлен. – frgtv10

2

Основная проблема заключается в том, что объединение внутри представления выполняется (без использования предложения where) до предложение where применяется для фильтрации этих строк.

Эффект: выберите каждую строку из обеих таблиц в гигантскую временную таблицу, а затем примените предложение where в этой временной таблице, конечно же, преимущество индекса (даже если оно существовало на базовых таблицах).

Вы можете попробовать использовать UNION ALL (а не только UNION), потому что UNION ALL сохраняет все строки, в то время как UNION отбрасывает дубликаты, который маскирует основную таблицу из результата из-за процесса де-оболванивания.


реальная проблема является база данных дизайн - две таблицы настолько похожи, что это довольно очевидно, что там должна быть только одна стол с isVariant колонки, чтобы отличить тип строки.Если вы не можете изменить таблицы, можно создать новую таблицу:

NewProduct 
ID | PID (fk to self for variants, null otherwise) | IsMaster | IsVariant | EAN | Name | Price .. 

И поставил индексы на любые столбцы, которые вы ищете на (EAN в данном случае).

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

+0

Благодарим вас за разъяснения. Это помогает мне и нажимает запрос вниз с 1 секунды до 0,7 секунды. Вы имеете в виду, что я должен попытаться построить запрос с объединениями вместо объединения? – frgtv10

+0

Может ли ваше приложение обрабатывать данные вместе в качестве соединения? – Bohemian

+0

Вы имеете в виду, что я должен попробовать использовать объединения, а не союз? Что вы имеете в виду с бок о бок? – frgtv10

0

Индексирование колонки EAN в обеих таблицах и попробуйте.

также попробовать это

explain (SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110') 
+0

Проблема заключается в том, что запрошенный u файл готов через примерно 0,0002 секунды. Но использование представления с условием, когда условие заняло до 1 секунды. – frgtv10

+0

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