Задавайте вопросы, мы ответим
Вы не зашли.
Коллеги помогите! Есть запрос объединяющий две разные таблицы A и Б. Мне требуется вывести элементы приведенные к одному виду и вывести их общее число. Код:
Отредактированно AvtoNom (20.11.2008 19:22:03)
Неактивен
1. SELECT SQL_CALC_FOUND_ROWS T.* ...
затем SELECT FOUND_ROWS()
http://dev.mysql.com/doc/refman/5.0/en/ … found-rows
2. Сначала выберите из всех таблиц какой-нибудь уникальный ключ и только его сортируете (желательно, первичный ключ - id) - тогда будет быстро - можно во временную таблицу. Затем вторым запросом через JOIN добираете остальные колонки.
Можно также дополнительное поле для сортировки создать: SELECT ..., @n := @n + 1 AS sort, а потом уже во втором запросе сделать ORDER BY sort.
Неактивен
1. да да. я нашел ответ на первый вопрос в топике http://sqlinfo.ru/forum/viewtopic.php?id=992
2. надо мне продумать... )))
Отредактированно AvtoNom (20.11.2008 20:19:04)
Неактивен
нашёл русский вариант статьи http://www.intuit.ru/department/databas … /11/5.html
так же нашел на форуме http://php.ru/forum/viewtopic.php?t=865 … torder=asc
Однако на большой базе это здорово тормозит, примерно так же, как с запросом без лимита.
Обычно намного быстрее будет использовать отдельный запрос с count(*)
Неактивен
SQL_CALC_FOUND_ROWS не будет замедлять запрос, если он все равно должен сортировать объединение таблиц. То есть большая таблица уже есть и подсчет полного числа строк не увеличит время выполнения. Бывают случаи, когда используется ключ и полная таблица не формируется - limit применяется сразу, но это, скорее всего не Ваш случай.
Способ обтимизации здесь - это избавление от UNION. Например создание временной MEMORY-таблицы, в которой уже выполнен UNION и пересчитывать ее, если данные в таблицах поменялись.
Неактивен
Однако на большой базе это здорово тормозит, примерно так же, как с запросом без лимита.
Обычно намного быстрее будет использовать отдельный запрос с count(*)
С лимитом быстрее, когда он по индексу сразу отсекает.
count(*) в MyISAM хранится отдельно, чтобы его отдать, не надо даже записи таблицы трогать, поэтому count(*) бывает быстрее. В InnoDB может быть по другому.
Неактивен
LazY написал:
С лимитом быстрее, когда он по индексу сразу отсекает.
count(*) в MyISAM хранится отдельно, чтобы его отдать, не надо даже записи таблицы трогать, поэтому count(*) бывает быстрее. В InnoDB может быть по другому.
Если есть WHERE, то уже не важно MyISAM или Innodb. Важно, используется ли ключ для LIMIT (такое бывает для несложных запросов). Судя по тому, что в приведенном запросе для WHERE и ORDER BY используются переменные PHP, следует предположить, что запрос сложный и потребует сортировку всей таблицы до LIMIT.
Неактивен
думаю теперь сделать так:
Отредактированно AvtoNom (21.11.2008 00:10:06)
Неактивен
Пока есть UNION запрос не будет оптимальным, но он может быть терпимым
Неактивен
rgbeast написал:
Бывают случаи, когда используется ключ и полная таблица не формируется - limit применяется сразу, но это, скорее всего не Ваш случай.
вы говрите о "Если LIMIT # используется с ORDER BY, MySQL закончит сортировку, как только найдет первые # строк, вместо того, чтобы сортировать всю таблицу. " ? взято с http://www.mysql.ru/docs/man/LIMIT_optimisation.html. У меня значение $sorter_str - и есть ORDER BY, но вроде сортирует правильно... Противоречие какое то!
rgbeast написал:
Способ обтимизации здесь - это избавление от UNION. Например создание временной MEMORY-таблицы, в которой уже выполнен UNION и пересчитывать ее, если данные в таблицах поменялись.
Мой второй вариант запроса наверное не нуждается во временной таблице? Для чего она вообще применяется? Столько пишу на php и мускуле что для самого странно что ни разу не использовал )) Не судите строго.
Неактивен
вопрос в догону... как определить является ли запрос оптимальным? я так понимаю всё упирается во время выполнения запроса? как его узнать?
Неактивен
LazY написал:
С лимитом быстрее, когда он по индексу сразу отсекает.
поясни пожалуйста что ты имел в виду?
Неактивен
rgbeast написал:
Пока есть UNION запрос не будет оптимальным, но он может быть терпимым
т.е. запрос вида
Отредактированно AvtoNom (25.11.2008 13:18:43)
Неактивен
rgbeast написал:
LazY написал:
С лимитом быстрее, когда он по индексу сразу отсекает.
count(*) в MyISAM хранится отдельно, чтобы его отдать, не надо даже записи таблицы трогать, поэтому count(*) бывает быстрее. В InnoDB может быть по другому.Если есть WHERE, то уже не важно MyISAM или Innodb. Важно, используется ли ключ для LIMIT (такое бывает для несложных запросов). Судя по тому, что в приведенном запросе для WHERE и ORDER BY используются переменные PHP, следует предположить, что запрос сложный и потребует сортировку всей таблицы до LIMIT.
AvtoNom написал:
LazY написал:
С лимитом быстрее, когда он по индексу сразу отсекает.
поясни пожалуйста что ты имел в виду?
Имел я в виду примерно то же, что и rgbeast: Как уже писал rgbeast:
Важно, используется ли ключ для LIMIT (такое бывает для несложных запросов).
Допустим, ORDER BY id LIMIT 10. На id ключ. Он видит, что для выбора того, какие записи показать, можно использовать ключ, начинает читать ключ (который по природе своей отсортирован), видит, что достиг записи c id = 10 и, поскольку ключ отсортирован, знает, что дальше нужных записей не будет (т.к. уже набралось 10 записей), и прекращает чтение таблицы; То есть, при этом чтение всегда простирается только на первые 10 записей и поэтому длится одинаково вне зависимости от того, сколько там записей - тысяча или миллион.
Как опять же отметил rgbeast, наверняка у Вас не простое условие где-то в ORDER BY или WHERE, и тогда так (как выше описано) не получится.
см. также http://dev.mysql.com/doc/refman/5.0/en/ … ation.html
Насчет count(*) я имел в виду следующее: count(*) без WHERE для таблицы MyISAM выполняется быстрее, чем для таблицы InnoDB, поскольку число записей хранится в таблицах MyISAM в явном виде, поэтому при прочих равных условиях для MyISAM выбрать, например, колонки-ключа (типа SELECT id FROM ...) будет много медленнее, чем просто COUNT(*), а для таблицы InnoDB - примерно так же.
Еще раз хочу подчеркнуть, что это только без WHERE.
см. также http://www.mysqlperformanceblog.com/200 … db-tables/
Насчет UNION.
Если Вам нужно две таблицы - выбирайте для каждой из них id во временные таблицы, потом для каждой из них подключайте через JOIN остальное и потом делайте UNION (только в том запросе, где UNION, уже сортировку не делайте, если это возможно - чтоб напрямую сразу шло).
А еще я не оч. понял, почему у Вас сомнения насчет вида UNION'а. Вам разве приложение такое позволяет?..
Вообще привели бы Вы свои WHERE и ORDER BY...
Неактивен
Насчет UNION.
LazY написал:
А еще я не оч. понял, почему у Вас сомнения насчет вида UNION'а. Вам разве приложение такое позволяет?..
сомнения возникли после ..
rgbeast написал:
Пока есть UNION запрос не будет оптимальным, но он может быть терпимым
Насчет вида? у меня UNION ALL.
Неактивен
LazY написал:
Если Вам нужно две таблицы - выбирайте для каждой из них id во временные таблицы, потом для каждой из них подключайте через JOIN остальное и потом делайте UNION (только в том запросе, где UNION, уже сортировку не делайте, если это возможно - чтоб напрямую сразу шло).
Вообще привели бы Вы свои WHERE и ORDER BY...
так не получится потому что я делаю лимит из ОБЩЕЙ отсортированной по времени таблице.
Неактивен
хотел бы ещё получить ответ на вопрос
AvtoNom написал:
как определить является ли запрос оптимальным? я так понимаю всё упирается во время выполнения запроса? как его узнать?
Неактивен
Оптимальным является индекс, который устраивает лично Вас
Узнать время выполнения запроса можно выполнив запрос и посчитав время его выполнения.
Клиент mysql это делает автоматически и пишет время после результатов запроса.
--
Тот запрос, который у Вас написан, имеет лишний SELECT снаружи, должно работать и более просто:
(SELECT ...) UNION (SELECT ...) ORDER BY ... LIMIT ...
Неактивен
сложновато понять. видно мне ещё многому учиться.... )
Неактивен
А конкретно что сложновато понять?
Неактивен
paulus написал:
Тот запрос, который у Вас написан, имеет лишний SELECT снаружи, должно работать и более просто:
(SELECT ...) UNION (SELECT ...) ORDER BY ... LIMIT ...
так не получится, про это я написал в сообщении #17.
paulus написал:
Клиент mysql это делает автоматически и пишет время после результатов запроса.
как получить это значеине в PHP?
-----------
в том же сообщении #17 мне кажется единственное улучшение запроса это введение лимита для каждого SELECT`а. И всё
Неактивен
Так получится, попробуйте
http://ru2.php.net/manual/ru/function.microtime.php до и после запроса. Ну и вычесть одно из другого.
Неактивен
спасибо за разьяснение первого вопроса, НО
второй вопрос топика остался открытым т.е. как оптимизировать?
Неактивен
Ответ на второй вопрос - см. пункт 5. Пока остается UNION будет неэффективное создание большой таблицы.
Неактивен
А если, допустим, UNION применять без сортировке по результирующей "супертаблице", (т.е. тупое слияние таблиц одна за другой), будет ли тормозить?
Неактивен