SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 20.11.2008 18:59:56

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

подскажите: count, union и оптимизация

Коллеги помогите! Есть запрос объединяющий две разные таблицы A и Б. Мне требуется вывести элементы приведенные к одному виду и вывести их общее число. Код:

"SELECT T.* FROM (
    (select a.id, a.id_from, 'letter' as type_table from А a ) UNION ALL
    (select s.id, s.user_id, null, 'shot' as type_table from Б s)    
    ) as T
     "
.$where_str."
     "
.$sorter_str."
 "
.$limit_str;


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

1. Как посчитать общее количество элементов не учитывая limit? Не делать же второй такой же сложный запрос только из-зи этого?!
2. Как я понимаю сначала здесь получается огромная таблица T а потом с ней производятся все действия. Мне кажется это не оптимально. Делать $where_str для каждой таблице мне кажется излишним усложнением алгоритма.

Отредактированно AvtoNom (20.11.2008 19:22:03)


Похоже я здесь надолго
=8-D

Неактивен

 

#2 20.11.2008 19:49:21

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: подскажите: count, union и оптимизация

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.

Неактивен

 

#3 20.11.2008 20:17:22

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

1. да да. я нашел ответ на первый вопрос в топике http://sqlinfo.ru/forum/viewtopic.php?id=992
2. надо мне продумать... )))

Отредактированно AvtoNom (20.11.2008 20:19:04)


Похоже я здесь надолго
=8-D

Неактивен

 

#4 20.11.2008 22:02:47

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

нашёл русский вариант статьи http://www.intuit.ru/department/databas … /11/5.html

так же нашел на форуме http://php.ru/forum/viewtopic.php?t=865 … torder=asc

Однако на большой базе это здорово тормозит, примерно так же, как с запросом без лимита.
Обычно намного быстрее будет использовать отдельный запрос с count(*)


Похоже я здесь надолго
=8-D

Неактивен

 

#5 20.11.2008 22:16:52

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: подскажите: count, union и оптимизация

SQL_CALC_FOUND_ROWS не будет замедлять запрос, если он все равно должен сортировать объединение таблиц. То есть большая таблица уже есть и подсчет полного числа строк не увеличит время выполнения. Бывают случаи, когда используется ключ и полная таблица не формируется - limit применяется сразу, но это, скорее всего не Ваш случай.

Способ обтимизации здесь - это избавление от UNION. Например создание временной MEMORY-таблицы, в которой уже выполнен UNION и пересчитывать ее, если данные в таблицах поменялись.

Неактивен

 

#6 20.11.2008 22:26:36

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: подскажите: count, union и оптимизация

Однако на большой базе это здорово тормозит, примерно так же, как с запросом без лимита.
Обычно намного быстрее будет использовать отдельный запрос с count(*)

С лимитом быстрее, когда он по индексу сразу отсекает.
count(*) в MyISAM хранится отдельно, чтобы его отдать, не надо даже записи таблицы трогать, поэтому count(*) бывает быстрее. В InnoDB может быть по другому.

Неактивен

 

#7 20.11.2008 22:34:30

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: подскажите: count, union и оптимизация

LazY написал:

С лимитом быстрее, когда он по индексу сразу отсекает.
count(*) в MyISAM хранится отдельно, чтобы его отдать, не надо даже записи таблицы трогать, поэтому count(*) бывает быстрее. В InnoDB может быть по другому.

Если есть WHERE, то уже не важно MyISAM или Innodb. Важно, используется ли ключ для LIMIT (такое бывает для несложных запросов). Судя по тому, что в приведенном запросе для WHERE и ORDER BY используются переменные PHP, следует предположить, что запрос сложный и потребует сортировку всей таблицы до LIMIT.

Неактивен

 

#8 20.11.2008 23:17:37

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

думаю теперь сделать так:

"SELECT SQL_CALC_FOUND_ROWS T.* FROM (
    (select a.id, a.id_from, a.id_to, 'letter' as type_table from А a where  "
.$where_str.") UNION ALL
    (select s.id, s.user_id, null, 'shot' as type_table from Б s where  "
.$where_str2.")    
    ) as T    
     "
.$sorter_str."
 "
.$limit_str;

потому что структура таблиц разная. или это тоже не оптимальный запрос?

Отредактированно AvtoNom (21.11.2008 00:10:06)


Похоже я здесь надолго
=8-D

Неактивен

 

#9 20.11.2008 23:20:45

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: подскажите: count, union и оптимизация

Пока есть UNION запрос не будет оптимальным, но он может быть терпимым

Неактивен

 

#10 20.11.2008 23:42:56

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, 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 и мускуле что для самого странно что ни разу не использовал )) Не судите строго.


Похоже я здесь надолго
=8-D

Неактивен

 

#11 20.11.2008 23:45:31

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

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


Похоже я здесь надолго
=8-D

Неактивен

 

#12 21.11.2008 00:07:42

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

LazY написал:

С лимитом быстрее, когда он по индексу сразу отсекает.

поясни пожалуйста что ты имел в виду?


Похоже я здесь надолго
=8-D

Неактивен

 

#13 21.11.2008 00:20:09

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

rgbeast написал:

Пока есть UNION запрос не будет оптимальным, но он может быть терпимым

т.е. запрос вида

"SELECT a.id, a.id_from, a.id_to, 'letter' as type_table, s.id, s.user_id, null, 'shot' as type_table from А a, Б s where  ".$where_str2." ".$where_str."    
     "
.$sorter_str."
 "
.$limit_str;
будет оптимальнее? тогда как мне определить к какой таблице относиться каждое значение из результата? раньше я разделял по значению "type_table from"

Отредактированно AvtoNom (25.11.2008 13:18:43)


Похоже я здесь надолго
=8-D

Неактивен

 

#14 21.11.2008 02:02:59

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: подскажите: count, union и оптимизация

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...

Неактивен

 

#15 25.11.2008 13:22:45

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

Насчет UNION.

LazY написал:

А еще я не оч. понял, почему у Вас сомнения насчет вида UNION'а. Вам разве приложение такое позволяет?..

сомнения возникли после ..

rgbeast написал:

Пока есть UNION запрос не будет оптимальным, но он может быть терпимым

Насчет вида? у меня UNION ALL.


Похоже я здесь надолго
=8-D

Неактивен

 

#16 25.11.2008 13:35:05

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

LazY написал:

Если Вам нужно две таблицы - выбирайте для каждой из них id во временные таблицы, потом для каждой из них подключайте через JOIN остальное и потом делайте UNION (только в том запросе, где UNION, уже сортировку не делайте, если это возможно - чтоб напрямую сразу шло).
Вообще привели бы Вы свои WHERE и ORDER BY...

так не получится потому что я делаю лимит из ОБЩЕЙ отсортированной по времени таблице.


SELECT t.* FROM ( (select a.id, a.id_from, a.id_to, DATE_FORMAT(a.date_creation, '%m-%d-%Y - %H:%i') as date_creation, a.body, a.type, a.was_read, a.approve, a.reply, 'letter' as type_table from messages a ) UNION ALL (select s.id, s.user_id, null, DATE_FORMAT(s.date_add, '%m-%d-%Y - %H:%i') as date_creation, s.text, null, null, s.approve, null, 'shot' as type_table from shout_messages s) ) as t order by date_creation DESC limit 0, 10


Похоже я здесь надолго
=8-D

Неактивен

 

#17 25.11.2008 13:36:44

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

хотел бы ещё получить ответ на вопрос

AvtoNom написал:

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


Похоже я здесь надолго
=8-D

Неактивен

 

#18 25.11.2008 15:24:50

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: подскажите: count, union и оптимизация

Оптимальным является индекс, который устраивает лично Вас smile

Узнать время выполнения запроса можно выполнив запрос и посчитав время его выполнения.
Клиент mysql это делает автоматически и пишет время после результатов запроса.

--

Тот запрос, который у Вас написан, имеет лишний SELECT снаружи, должно работать и более просто:
(SELECT ...) UNION (SELECT ...) ORDER BY ... LIMIT ...

Неактивен

 

#19 26.11.2008 01:27:37

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

сложновато понять. видно мне ещё многому учиться.... )


Похоже я здесь надолго
=8-D

Неактивен

 

#20 26.11.2008 13:47:43

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: подскажите: count, union и оптимизация

А конкретно что сложновато понять? smile

mysql> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)


Время выполнения - в скобках (0.00).

Неактивен

 

#21 26.11.2008 17:03:56

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

paulus написал:

Тот запрос, который у Вас написан, имеет лишний SELECT снаружи, должно работать и более просто:
(SELECT ...) UNION (SELECT ...) ORDER BY ... LIMIT ...

так не получится, про это я написал в сообщении #17.

paulus написал:

Клиент mysql это делает автоматически и пишет время после результатов запроса.

как получить это значеине в PHP?

-----------
в том же сообщении #17 мне кажется единственное улучшение запроса это введение лимита для каждого SELECT`а. И всё sad


Похоже я здесь надолго
=8-D

Неактивен

 

#22 26.11.2008 21:44:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: подскажите: count, union и оптимизация

Так получится, попробуйте wink

http://ru2.php.net/manual/ru/function.microtime.php до и после запроса. Ну и вычесть одно из другого.

Неактивен

 

#23 27.11.2008 19:28:22

AvtoNom
Завсегдатай
Зарегистрирован: 20.11.2008
Сообщений: 33

Re: подскажите: count, union и оптимизация

спасибо за разьяснение первого вопроса, НО

второй вопрос топика остался открытым sad т.е. как оптимизировать?


Похоже я здесь надолго
=8-D

Неактивен

 

#24 27.11.2008 20:35:24

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: подскажите: count, union и оптимизация

Ответ на второй вопрос - см. пункт 5. Пока остается UNION будет неэффективное создание большой таблицы.

Неактивен

 

#25 29.11.2008 00:06:21

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: подскажите: count, union и оптимизация

А если, допустим, UNION применять без сортировке по результирующей "супертаблице", (т.е. тупое слияние таблиц одна за другой), будет ли тормозить?

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson