Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: UNION

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: убожество
Fobius
Отправлено: 23 Ноября, 2010 - 21:09:09
Post Id


Гость


Покинул форум
Сообщений всего: 96
Дата рег-ции: Нояб. 2009  


Помог: 1 раз(а)




Довольно интересная ситуация. На этом форуме мне несколько раз говорили, что запросы в БД надо обьединять и по максимуму переваливать задачи на сторону БД.

Тогда как обьяснить следующее:
PHP:
скопировать код в буфер обмена
  1. $result[1] = mysql_query("SELECT * FROM `news` WHERE `type` = 11 or `type` = 12 or `type` = 13 or `type` = 14 or `type` = 15 ORDER BY `tsdate` DESC LIMIT 6");
  2. $result[2] = mysql_query("SELECT * FROM `news` WHERE `type` = 21 or `type` = 22 or `type` = 23 or `type` = 24 or `type` = 25 or `type` = 26 ORDER BY `tsdate` DESC LIMIT 6");
  3. $result[3] = mysql_query("SELECT * FROM `news` WHERE `type` = 31 or `type` = 32 or `type` = 33 or `type` = 34 ORDER BY `tsdate` DESC LIMIT 6");
  4. $result[4] = mysql_query("SELECT * FROM `news` WHERE `type` = 41 or `type` = 42 or `type` = 43 or `type` = 44 ORDER BY `tsdate` DESC LIMIT 6");
  5. $result[5] = mysql_query("SELECT * FROM `news` WHERE `type` = 50 ORDER BY `tsdate` DESC LIMIT 6");
  6. $result[6] = mysql_query("SELECT * FROM `news` WHERE `type` = 60 ORDER BY `tsdate` DESC LIMIT 6");
  7. $result[7] = mysql_query("SELECT * FROM `news` WHERE `type` = 70 ORDER BY `tsdate` DESC LIMIT 6");
  8. $result[8] = mysql_query("SELECT * FROM `news` WHERE `type` = 80 ORDER BY `tsdate` DESC LIMIT 6");
  9. $result[9] = mysql_query("SELECT * FROM `news` WHERE `type` = 90 ORDER BY `tsdate` DESC LIMIT 6");


срок выполнения: 0,008

обьеденил:
PHP:
скопировать код в буфер обмена
  1. $result = mysql_query("
  2.    (SELECT * FROM `news` WHERE `type` = 11 or `type` = 12 or `type` = 13 or `type` = 14 or `type` = 15 LIMIT 6)
  3.        UNION
  4.    (SELECT * FROM `news` WHERE `type` = 21 or `type` = 22 or `type` = 23 or `type` = 24 or `type` = 25 or `type` = 26 LIMIT 6)
  5.        UNION
  6.    (SELECT * FROM `news` WHERE `type` = 31 or `type` = 32 or `type` = 33 or `type` = 34 LIMIT 6)
  7.        UNION
  8.    (SELECT * FROM `news` WHERE `type` = 41 or `type` = 42 or `type` = 43 or `type` = 44 LIMIT 6)
  9.        UNION
  10.    (SELECT * FROM `news` WHERE `type` = 50 LIMIT 6)
  11.        UNION
  12.    (SELECT * FROM `news` WHERE `type` = 60 LIMIT 6)
  13.        UNION
  14.    (SELECT * FROM `news` WHERE `type` = 70 LIMIT 6)
  15.        UNION
  16.    (SELECT * FROM `news` WHERE `type` = 80 LIMIT 6)
  17.        UNION
  18.    (SELECT * FROM `news` WHERE `type` = 90 LIMIT 6)
  19.        ORDER BY `tsdate` DESC");


срок выполнения 10-13сек

Ну и как это?? Один чуть сложнее запрос исполняется в полторы тысячи раз дольше, чем 9 отдельных запросов...
как это??

(Отредактировано автором: 23 Ноября, 2010 - 21:10:28)

 
 Top
Мелкий Супермодератор
Отправлено: 23 Ноября, 2010 - 22:56:29
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Это время запроса? А что хотели? Union довольно медлителен.
А померяйте время исполнения скрипта через microtime. Если разница та же - то таки поздравляю вас.

Fobius пишет:
`type` = 21 or `type` = 22 or `type` = 23 or `type` = 24 or `type` = 25 or `type` = 26

type>=21 and type<=26 не понятнее будет написать? Или type in (21,22,23,24,25,26).

Кажется мне, что в момент публикации сообщения цифры разницы были куда меньше.

(Отредактировано автором: 23 Ноября, 2010 - 22:58:18)



-----
PostgreSQL DBA
 
 Top
Fobius
Отправлено: 24 Ноября, 2010 - 08:13:38
Post Id


Гость


Покинул форум
Сообщений всего: 96
Дата рег-ции: Нояб. 2009  


Помог: 1 раз(а)




так я и мерял через (time() + microtime(1))
И цифры не меняются. Да, конечно, беда в том что у меня денвер, установленный на флешку (старую), на хостинге будет быстрее, но всеравно разница в полторы тысячи раз!
а с запросами к базе я уже боюсь эксперементировать, стараюсь их делать как можно приметивнее. Потому что половина примеров вообще нехочет работать(говорят mysql очень обрезан), остальное медлительно. У меня на эти запросы боязнь развилась.

Может UNION и медлителен, но почему он более медлителен чем 9 отдельных запросов? Зачем он тогда?
 
 Top
Uchkuma
Отправлено: 24 Ноября, 2010 - 10:04:24
Post Id



Участник


Покинул форум
Сообщений всего: 1539
Дата рег-ции: Март 2010  
Откуда: Киров


Помог: 6 раз(а)




Интересно, почему сортировку по разному делаете?
 
 Top
Fobius
Отправлено: 24 Ноября, 2010 - 11:50:12
Post Id


Гость


Покинул форум
Сообщений всего: 96
Дата рег-ции: Нояб. 2009  


Помог: 1 раз(а)




почему по разному? В обоих случаях по `tsdate` DESC, только в запросе с UNION приходится сортировку ко всему запросу делать, потому что по отдельным вложеным ORDER не работает. А так надо каждый раз mysql_data_seek() делать и проверять все с помощью if($row[type] == $i).
Вот я и думаю, где его вообще использовать, этот UNION и зачем...
 
 Top
JustUserR
Отправлено: 24 Ноября, 2010 - 18:04:06
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




Fobius Приведенная вами реализации сортировки информаицонных полей полученных в результате совмещенной выборки в действительности отличается от предполагаемого изначального вариана - поскольку включает в себя генерацию отельного неименованного списка элементов с осществленем сортировки внутри него - вместо выполненя внутренней операции по индексированным компонентам


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
dc93
Отправлено: 27 Ноября, 2010 - 17:17:33
Post Id


Новичок


Покинул форум
Сообщений всего: 21
Дата рег-ции: Нояб. 2010  


Помог: 0 раз(а)




Fobius пишет:
Довольно интересная ситуация. На этом форуме мне несколько раз говорили, что запросы в БД надо обьединять и по максимуму переваливать задачи на сторону БД.

срок выполнения 10-13сек

Ну и как это?? Один чуть сложнее запрос исполняется в полторы тысячи раз дольше, чем 9 отдельных запросов...
как это??


А с чего это вдруг случилось, что то, что Вы написали в отдельных запросах и через UNION - это одно и тоже?

Если хотите тупо объединить запросы в один, используйте UNION ALL (надеюсь, разницу объяснять не нужно)
 
 Top
Fobius
Отправлено: 28 Ноября, 2010 - 18:25:51
Post Id


Гость


Покинул форум
Сообщений всего: 96
Дата рег-ции: Нояб. 2009  


Помог: 1 раз(а)




dc93 пишет:
А с чего это вдруг случилось, что то, что Вы написали в отдельных запросах и через UNION - это одно и тоже?

Это одно и тоже, только отсортировано поразному. Если UNION ALL, то еще +1.5-2сек. Страшные цифры.

беда...

(Отредактировано автором: 28 Ноября, 2010 - 18:27:54)

 
 Top
Champion Супермодератор
Отправлено: 28 Ноября, 2010 - 19:18:03
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




dc93 пишет:
Если хотите тупо объединить запросы в один, используйте UNION ALL (надеюсь, разницу объяснять не нужно)
Разница в том, что UNION ALL не будет исключать из результата одинаковые строки, выбранные разными запросами объединения. При чем тут это?

Fobius Объединять запросы - конечно хорошо, но делать такую кучу юнионов - это лишнее. Вот чего действительно стоит избегать, так это однотипных запросов в цикле. Из лучше преобразовывать в один запрос.

А по поводу скорости выполнения - тут что-то действительно необъяснимое. Надо тоже поэксперементировать.

У меня, кстати, тоже была недавно проблема с таким удивительным поведением. Сводилась она к тому, что select * from (select * from tbl) t where t.field = 345 Работало по-разному на 2 версиях Mysql. На одном индекс по field использовался при выборке, на другом - нет. Пришлось удивиться и переписать запрос.
 
 Top
dc93
Отправлено: 28 Ноября, 2010 - 19:37:31
Post Id


Новичок


Покинул форум
Сообщений всего: 21
Дата рег-ции: Нояб. 2010  


Помог: 0 раз(а)




Champion
Цитата:
Разница в том, что UNION ALL не будет исключать из результата одинаковые строки, выбранные разными запросами объединения. При чем тут это?


это риторический вопрос?

(так как именно из-за исключения _одинаковых_ строк время выполнения может увеличиться на несколько порядков)

Цитата:
А по поводу скорости выполнения - тут что-то действительно необъяснимое


ага, уж такое необъяснимое, прям "есть ли жизнь на марсе"

Цитата:
На одном индекс по field использовался при выборке, на другом - нет. Пришлось удивиться и переписать запрос.


может проще было статистику обновить? в обоих случаях данные в таблицах были одинаковые?

зы в некоторых случаях оптимизатор вполне обоснованно отказывается от использования индексов

Fobius
Цитата:
Это одно и тоже, только отсортировано поразному.


ого, я такого еще не слышал... откуда "дровишки"?
 
 Top
Champion Супермодератор
Отправлено: 28 Ноября, 2010 - 20:02:12
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




dc93 пишет:
время выполнения может увеличиться на несколько порядков)
Никак не на несколько порядков. В худшем случае каждый следующий подходящий результат будет задерживаться на log[осн2](N). N - количество уже найденных записей.
Вообще конечно да, union all предпочтительнее, хотя судя по where и так не будет повторяющихся столбцов.

dc93 пишет:
ага, уж такое необъяснимое, прям "есть ли жизнь на марсе"
Ну расскажи-ка. Мне тоже интересно. Чем union 2 запросов отличается от выполнения их по очереди?
Кстати, Fobius, а без сортировок какая картина получается?

dc93 пишет:
в обоих случаях данные в таблицах были одинаковые?
Абсолютно. И индексы были только что созданы в обоих серверах, так что смысла обновлять статистику большого не было. Индекс хороший, почти уникальный. Оптимизатору незачем было его игнорировать. Кроме того запрос просто select * from tbl where field = 345 индексом пользовался. А такие не хотели.
 
 Top
dc93
Отправлено: 28 Ноября, 2010 - 20:31:33
Post Id


Новичок


Покинул форум
Сообщений всего: 21
Дата рег-ции: Нояб. 2010  


Помог: 0 раз(а)




Champion
Цитата:
Никак не на несколько порядков. В худшем случае каждый следующий подходящий результат будет задерживаться на log[осн2](N). N - количество уже найденных записей.


:)
Вы не учитываете две вещи:
1) Выведенные уже результаты надо серверу где-то хранить (для последующего сравнения, даже если это будут просто номера строк или физические адреса начала памяти строк, хотя в этом смысла мало, т.к. тогда всеравно придется за каждой строкой лазить:), соответственно используется некая WorkTable

2) В зависимости от "разного" эта табличка может быть создана на HD

я думаю, что дальше эту ужасающую картинку можно не расписывать
Цитата:
Вообще конечно да, union all предпочтительнее,


разница почти как между обычным селектом и селектом с группировкой

Цитата:
судя по where и так не будет повторяющихся столбцов


поверьте, серверу от этого ничуть не легче (он пока не проверит всеравно не поверит) :)

Цитата:
Чем union 2 запросов отличается от выполнения их по очереди?

при отсутствии сортировки UNION ALL почти что ничем, серверу единственно придется проверить поля на соответствии типов, но это копейки,

про UNION же, мне кажется, я уже довольно подробно все объяснил

Цитата:
И индексы были только что созданы в обоих серверах, так что смысла обновлять статистику большого не было.

ИМХО, Вы тут слегка путаете: только что созданный индекс или давно и карраптнутый (к примеру) разницы не играет.
На основе статистики оптимизатор принимает решение использовать ему индекс или нет, например, если у оптимизатора собственное мнение, что Вы собираетесь выбрать процентов 15 из таблицы, то он отключит индекс, а вот это мнение оптимизатор строит на основе статистики
 
 Top
Champion Супермодератор
Отправлено: 29 Ноября, 2010 - 08:42:38
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




dc93 пишет:
ИМХО, Вы тут слегка путаете: только что созданный индекс или давно и карраптнутый (к примеру) разницы не играет.
Не, я к тому, что по новому индексу актуальная статистика и ее пересчет скорее всего не очень поможет. Индекс был создан, когда все данные уже были вставлены. Ну да ладно, в этой теме не мой вопрос обсуждается.

По Union / Union All я согласен, но в это теме я вот что вижу:
- 9 отдельный запросов, в каждом из которых есть сортировка и забирание первых 6 записей.
- Те же 9 запросов, только без сортировки, в которых просто берутся первые 6 записей, объединяются юнионом, потом один раз результат сортируется.

Или я в чем-то не прав? Откуда такая разница тут в скорости?
 
 Top
dc93
Отправлено: 29 Ноября, 2010 - 10:33:05
Post Id


Новичок


Покинул форум
Сообщений всего: 21
Дата рег-ции: Нояб. 2010  


Помог: 0 раз(а)




Champion

черт, глаз замылился, "слона то я и не приметил" :(
Цитата:
- 9 отдельный запросов, в каждом из которых есть сортировка и забирание первых 6 записей.
- Те же 9 запросов, только без сортировки, в которых просто берутся первые 6 записей, объединяются юнионом, потом один раз результат сортируется


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

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

Цитата:
Не, я к тому, что по новому индексу актуальная статистика и ее пересчет скорее всего не очень поможет. Индекс был создан, когда все данные уже были вставлены. Ну да ладно, в этой теме не мой вопрос обсуждается.



ИМХО, это не так, ИМХО, статистика при создании/удалении/перестроении индекса не обновляется
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB