| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > СУБД, общие вопросы > замена left join? |
| Автор: yezh 29.11.2007, 09:53 |
| Народ, а вы не знаете как можно заменить left join на конструкцию в where? А то left join оч сильно тормозит, и единственный способ оптимизировать время аботы запроса это убрать его |
| Автор: boevik 29.11.2007, 09:57 |
| в общем случае JOIN нельзя заменить через WHERE, ведь по какому то признаку таблицы должны соединяться. Возможно улучшить производительность использованием PK и соотвествующх индексов. Копай в эту сторону. |
| Автор: yezh 29.11.2007, 10:13 | ||
Накопано все что можно. Дальше просто некуда. А left join используется для связи двух таблиц, т.е. примерно такая конструкция:
Я полагал что такая конструкция может быть заменена на что то другое... |
| Автор: skyboy 29.11.2007, 10:29 |
| yezh, посмотри то, что тебе выдает http://dev.mysql.com/doc/refman/5.1/en/explain.html. Скорее всего, у тебя в присоединении не используются ключи(индексы), или же у тебя происходит сортировка/группировка большого количества строк. сделай explain запросу и приведи здесь, что оно возвращает. |
| Автор: yezh 29.11.2007, 10:41 |
| дело в том, что column1 и column2 - это ключи. А база данных - Pervasive, ключи же используемые нулевые (аля примари). Просто именно эта субд страдает тормознутостью при использовании джоинов, и лучше их на больших таблицах (а в данном случае размер одной таблицы превышает 300 мб) не юзать. |
| Автор: skyboy 29.11.2007, 11:37 |
один составной ключ или два "простых"? |
| Автор: yezh 29.11.2007, 11:38 |
| один составной |
| Автор: skyboy 29.11.2007, 11:38 |
это СУБД такая? насчет explain'a - извини, это для mysql. Добавлено @ 11:46 смотрю, там только http://www.pervasive.com/library/docs/psql/10/sqlref/sqlref-13-5.html доступен, и то - в очень урезанном виде информация выдается... Добавлено @ 11:48 впрочем, даже у такой скромной штуковины, как http://www.pervasive.com/library/docs/psql/10/sqlref/sqlref-13-1.html есть http://www.pervasive.com/library/docs/psql/10/sqlref/sqlref-13-3.html#wp82883 |
| Автор: yezh 29.11.2007, 12:30 |
| Мде :(. Так то 10 версия, а у нас 8-ка. ПО 8-ке же инфы такой не вижу... Но это пока ладно, меня больше интересует вопрос, нет ли какого способа переделать запрос? Т.е. можно ли в общем случае отказаться от лефт джоин в пользу условий, и как это может выглядеть? |
| Автор: skyboy 29.11.2007, 12:42 |
| yezh, потенциально возможно только INNER JOIN "свернуть" до WHERE, да и то - скорость должна быть такая же. а запрос, который ты привел, он и есть полный? |
| Автор: yezh 29.11.2007, 13:07 | ||
Насчет скорости ты не прав: без INNER JOIN запрос работает гораздо быстрее (я так сократил время выполнения запроса с 8 мин до 10 сек) Почти полный. Используется еще одно поле в left join, но это не ключ. |
| Автор: Deniz 29.11.2007, 16:18 |
| Вот об этом поподробнее... Добавлено через 2 минуты и 49 секунд skyboy, раньше (давно было, еще на версии 6.15) Btrieve отличался приличной скоростью. Может что в филармонии не так? Это вопрос к автору. |
| Автор: yezh 30.11.2007, 10:51 | ||
Нате вам запрос полный.
ключи - поля с1 и с2 |
| Автор: skyboy 30.11.2007, 12:30 | ||
попробуй убрать констатнтые выражения
быстрее? намного? |
| Автор: Akina 30.11.2007, 12:38 |
А что вообще делают условая отбора в выражении связывания? |
| Автор: skyboy 30.11.2007, 12:52 |
подозрительно, правда? возможно, именно из-за этого тормозит. правда, в WHERE не кинешь - это же LEFT JOIN, потому если перебросить условия в WHERE, то потеряем часть строк, для которых t2.RefValue <> 0 или t2.AttrID <> '' |
| Автор: Deniz 30.11.2007, 14:56 |
| а вдруг так быстрее будет? Может оптимизатор не умеет/не хочет использовать индекс по с1 и с2 при наличии дополнительного условия связывания? |
| Автор: Akina 30.11.2007, 15:10 | ||
да я вообще не понимаю этой фигни в условиях отбора... как оно работать-то будет? с одной стороны left join - значит, все записи из t2 должны войти в результирующий набор независимо ни от чего... с другой - какие-то условия связывания... это что, в результате не будет выполняться связывание с записями, что не отвечают условиям, но в результирующий набор они все одно войдут? с null-ами в t1.*? по-моему, лучше построить 2 отдельных запроса и слить их результаты... |
| Автор: yezh 30.11.2007, 15:13 | ||||||
А как я уберу константые выражения???? У меня рез-т запроса будет совершенно иной! 2 запроса нельзя сделать по разным причинам. Одна из них - нарушится маппинг рез-тов запроса на класс, чего делать нельзя. А вот если бы можно было сделать два запроса и слить их при помощи sql (не программными методами), это ьыло ьы замечательно... Вообще говоря я уже убрал left join, при помощи union'a, однако... запрос работает еще медленнее :( Добавлено через 8 минут и 34 секунды
Народ, а может я не понимаю как работает left join? Мое такое мнение: выбираются все строки из таблицы t1, удовлетворяющие условию в where, затем к рез-ту пристыковываются строки из t2, которые соответствуют условиям в блоке ON |
| Автор: skyboy 30.11.2007, 15:38 | ||||||
нет. left-join'ится t2, значит, null'ы будут в t2.* Добавлено через 1 минуту и 34 секунды
именно так. если соотвествующих строк в t2 не окажется, то будут "присоединены" NULL'ы. Впрочем, такой запрос подозрительно выглядит. может, можно переджелать структуру БД, чтоб избежать таких запросов? можно получить информацию по логике запроса? что он вообще моделирует? Добавлено через 2 минуты и 56 секунд
меня интересует, в первую очередь, найти действительно узкое место запроса. я не предлагаю тебе просто эти условия удалить, я предлагаю провести эксперимент. который, при отсутствии средств профилирования(говоришь, у тебя 8-я версия, и там нужных инструментов нет?) позволит определить - что же так сильно тормозит. |
| Автор: yezh 30.11.2007, 15:54 |
| Узкое место? Join. Если просто перенести все условия в where (невзирая на то, что рез-т неполным получится), то работать такой запрос будет порядка 4-х секунд. Если с join - порядка минуты. Переделать структуру базы я не могу - база от чужого приложения. Т.е. заполняется она именно этим приложением, я лишь беру от туда данные. Запрос же просто получает действия клиента за поределенный промежуток времени. А таких действий оч много (много клиентов), отсюда огромный размер базы Добавлено через 1 минуту и 41 секунду Убирание константных условий не помогло, время выполнения то же. |
| Автор: Akina 30.11.2007, 16:12 |
| Погоди... ты сказал раньше, что у тебя один составной ключ (что очевидно, двух ключей не бывает) - а связываешь по отдельным полям. Гарантированно одно из двух условий связывания не использует ключа. Попробуй связывать строго по тому выражению, которое используется при построении этого первичного ключа. |
| Автор: yezh 30.11.2007, 16:33 |
| Ммм.. первазив ето такая база в которой может быть скок угодно ключей .. хоть сто Если при связывании использовать это выражение, то у меня будут дублироваться записи Ключ на самом деле не совсем первичный, в том смысле что он не уникальный. Однако поиск по нему должен выполняться в первую очередь |
| Автор: skyboy 30.11.2007, 17:29 |
оффтоп: помедитировав, пришел к выводу, что Akina под "ключом" понимает "первичный ключ", а ты - любой индекс. просто несоотвествие "внутренних" терминологий походу, ключ при связывании не используется. странно :( А если перейти к inner join - скорость возрастет? |
| Автор: Akina 30.11.2007, 17:43 | ||
skyboy, ты медитируешь лучше... |
| Автор: skyboy 30.11.2007, 17:53 | ||||
не знаю, как в Pervasive, а вот MSSQL и MySQL(с чем работал; по идее, все остальные внеяемые СУБД - тоже) если идет условие(в WHERE или JOIN) на все, включенные в составной индекс поля, применяет обработку этого составного индекса. Не думаю, что Pervasive настолько идиотична, чтоб это игнорировать. А иначе - смысл в составном индексе, если его негде использовать? Вот только мысль есть: а порядок полей в условии такой же, как порядок объявленного следования в индексе(ключе)? Я с Pervasive не работал, но оптимизатор его подозреваю во всех тяжких. -- оффтоп: ещё тут попутно вопрос:
я правильно понял: ты условия связывания в INNER JOIN переместил в секцию WHERE и заработало быстрее? или ты просто объявил INNER JOIN без условия связывания? -- Что-что? |
| Автор: Akina 30.11.2007, 17:58 | ||
Да? как я понял из документации, индекс используется только при обработке выражений с теми полями и их частями, которые стоят в начале выражения для построения индекса... |
| Автор: skyboy 30.11.2007, 18:09 | ||
немного перекрученно изложил. индекс может(зависит от оптимизатора) использоваться при обработке выражений, в которые входят все поля, включенные в индекс, либо только те поля, которые стоят первыми при организации индекса. чтоб остальных не запутывать, приведу аналогию: если есть список телефонов, где идет разбивка по городам, затем - по улицам, затем - по номерам домов, то найти телефон, имея все данные - просто, имея названия города и улицы - тоже проще, чем перебирать все. но если из всех данных есть только название города и номер дома(улица не указана), то потенциально быстрее просмотреть таблицу без использования индекса. не понял только, для чего ты это привел. считаешь, что индекс в запросе yezhа использоваться не может? Добавлено @ 18:36 yezh, а можно сервер будет обновить? |
| Автор: yezh 30.11.2007, 18:40 |
| Ок, товарищи, проблема решена. Оказывается, в запросе участвовала не таблица, а структура наложенная на таблицу. Некие же умные программисты в структуру индексов вообще не внесли. После внесения индексов время работы запросы резко уменьшилось Убыв бы таких Всем огромное спасибо З.Ы. Кстати, иногда (не знаю почему), бывает такое, что несмотря на все индексы запросы в первазиве работают оч долго (чаще всего при использовании INNER JOIN). Был один такой случай, долго мучались, решили проблему только уберанием этой конструкции. Это вдруг если кто то захочет использовать Pervasive SQL v8.7 |
| Автор: Akina 30.11.2007, 18:46 | ||||||
Скажем так - не вижу гарантий, что он использоваться будет. Однако конструкция вот такого типа:
при составных индексах по (t1.v1 & t1.v2) и (t2.v3 & t2.v4) на MS Access и MS SQL летает много быстрее, чем
|
| Автор: Deniel_li 6.12.2007, 15:30 | ||
| если запрос имеет именно такой вид, то смело меняйте на where у вас нигде нет условий на null значения, а этот кусочек
не подразумевает использование записей из t1 для которых в t2 нет значений |