BG Development


Страници: (3) 1 2 [3]   ( Първото ново мнение ) Reply to this topicStart new topicStart Poll

> MYSQL - JOIN на таблица със себе си
johnfound
Публикувано на: 02-08-2018, 07:57
Quote Post


Group Icon
Име:
Група: VIP
Ранг: Почетен член

Мнения: 7631
Регистриран на: 27.05.04



QUOTE (dvader @ 02-08-2018, 07:24)
Защото нямаш индекси?

Имам индекси.

В конкретния случа проблема е заради left join-a - защото с inner join се индексира нормално и скоростта се вдига значително. Пак е приблизително 1.5..2 пъти по-бавно от варианта със под заявката (примерно 2500мкс срещу 1800мкс) но все пак не е десет пъти. Ето резултата от "explain query plan":

CODE
explain query plan
select p.* from posts p left join users u on u.id = p.userid where nick = "johnfound";

SCAN TABLE posts AS p
SEARCH TABLE users AS u USING COVERING INDEX idxUsers_nick (nick=? AND rowid=?)


explain query plan
select p.* from posts p join users u on u.id = p.userid where nick = "johnfound";

SEARCH TABLE users AS u USING COVERING INDEX sqlite_autoindex_Users_1 (nick=?)
SEARCH TABLE posts AS p USING INDEX idxPosts_UserID (userID=?)


explain query plan
select p.* from posts p where userid = (select id from users where nick="johnfound");

SEARCH TABLE posts AS p USING INDEX idxPosts_UserID (userID=?)
EXECUTE SCALAR SUBQUERY 1
SEARCH TABLE users USING COVERING INDEX sqlite_autoindex_Users_1 (nick=?)


sqlite_autoindex_Users_1 е автоматичен индекс, създаден, защото колоната users.nick е unique.

Разбира се, проблема може да е и в оптимизатора, който понякога се държи като квантова величина - в смисъл съвършено непредсказуемо. icon_lol.gif


--------------------
asm32 - Приложно програмиране на асемблер.
Tox: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9
PMEmail PosterUsers Website
Top
ldbl
Публикувано на: 02-08-2018, 09:41
Quote Post



Име: Станислав Неделчев
Група: Потребител
Ранг: Редовен член

Мнения: 357
Регистриран на: 22.09.07



Интересно е защо с join не работи достатъчно бързо ако има индекси.
В интерес на истината и аз избягвам да пиша подобни под заявки , не само сащото може да върбе два резултата , но и като цяло са по бавни.
Освен това вече избягвам и join icon_smile.gif навъдиха се разни бази където не могат да правят disk based joins и ако не стигне паметта и fail.


--------------------
PMEmail PosterUsers WebsiteICQ
Top
PxL
Публикувано на: 02-08-2018, 09:52
Quote Post


Group Icon
Име: Димитър Т. Димитров
Група: VIP
Ранг: Почетен член

Мнения: 2940
Регистриран на: 26.04.05



QUOTE (johnfound @ 02-08-2018, 08:57)
QUOTE (dvader @ 02-08-2018, 07:24)
Защото нямаш индекси?

Имам индекси.

В конкретния случа проблема е заради left join-a - защото с inner join се индексира нормално и скоростта се вдига значително. Пак е приблизително 1.5..2 пъти по-бавно от варианта със под заявката (примерно 2500мкс срещу 1800мкс) но все пак не е десет пъти. Ето резултата от "explain query plan":

CODE
explain query plan
select p.* from posts p left join users u on u.id = p.userid where nick = "johnfound";

SCAN TABLE posts AS p
SEARCH TABLE users AS u USING COVERING INDEX idxUsers_nick (nick=? AND rowid=?)


explain query plan
select p.* from posts p join users u on u.id = p.userid where nick = "johnfound";

SEARCH TABLE users AS u USING COVERING INDEX sqlite_autoindex_Users_1 (nick=?)
SEARCH TABLE posts AS p USING INDEX idxPosts_UserID (userID=?)


explain query plan
select p.* from posts p where userid = (select id from users where nick="johnfound");

SEARCH TABLE posts AS p USING INDEX idxPosts_UserID (userID=?)
EXECUTE SCALAR SUBQUERY 1
SEARCH TABLE users USING COVERING INDEX sqlite_autoindex_Users_1 (nick=?)


sqlite_autoindex_Users_1 е автоматичен индекс, създаден, защото колоната users.nick е unique.

Разбира се, проблема може да е и в оптимизатора, който понякога се държи като квантова величина - в смисъл съвършено непредсказуемо. icon_lol.gif

Определено проблема ти е при оптимизатора. Пуска SCAN за индексирано поле.

Също не ми е ясно как имаш разлики във времената при inner join-a при положение, че от това, което си дал прави същото като подзаявката в where.

Това мнение е било редактирано от PxL на 02-08-2018, 09:56


--------------------
void putchar(char c);int main(){int x,c=1,i;for(i=0;(x="PxLY2H4:2E;7231?=68255A5S5P9N:N9O84111H861I85111G9N:O811O812M<G33911EAEDBECE22169D1=2k"[i+++3]);)while(x-->'0')putchar((!(++c%'('))?0x0a:33^(i&1));}
PMEmail PosterUsers Website
Top
johnfound
Публикувано на: 02-08-2018, 10:22
Quote Post


Group Icon
Име:
Група: VIP
Ранг: Почетен член

Мнения: 7631
Регистриран на: 27.05.04



QUOTE (ldbl @ 02-08-2018, 10:41)
...и аз избягвам да пиша подобни под заявки...

...Освен това вече избягвам и join icon_smile.gif...

Няма как да избягаш от двете едновременно! icon_eek.gif Или ще е едното или другото.

Разбира се, с join е далеч по-чисто, отколкото с подзаявки. Които аз също избягвам. Но в някои конкретни завъртени частни случаи, може да се получи по-бързо с подзаявки.

QUOTE (PxL @ 02-08-2018, 10:52)
Също не ми е ясно как имаш разлики във времената при inner join-a при положение, че от това, което си дал прави същото като подзаявката в where.


И аз се чудя. Съдейки по explain-а, се различава само реда на изпълнението на заявките. Може да е резултат от някакви кеширания в паметта, или реда на дисковите операции, или фазите на луната... icon_confused.gif


--------------------
asm32 - Приложно програмиране на асемблер.
Tox: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9
PMEmail PosterUsers Website
Top
fast_user
Публикувано на: 02-08-2018, 11:17
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 583
Регистриран на: 19.09.12



QUOTE (johnfound @ 01-08-2018, 23:41)
За да не съм голословен ето две еквивалентни заявки, едната с join другата с подзаявка (таблиците са от AsmBB защото това имам под ръка в момента):

CODE
select * from posts where userid = (select id from users where nick="johnfound");

select p.* from posts p left join users u on u.id = p.userid where nick = "johnfound";

Aко са еквивалентни заявките, защо едната вади повече редове от другата, или си я пускал само в база с постове с nick = johnfound.
Иначе да, ако не знаеш кога да ползваш inner и кога left, верно с подзаявки е по-добре.

Това мнение е било редактирано от fast_user на 02-08-2018, 11:17


--------------------
Linux is only free if your time has no value.
Linux Akbar
Чък Норис не използва Линукс, Линукс използва Чък Норис.
PMEmail Poster
Top
johnfound
Публикувано на: 02-08-2018, 11:54
Quote Post


Group Icon
Име:
Група: VIP
Ранг: Почетен член

Мнения: 7631
Регистриран на: 27.05.04



QUOTE (fast_user @ 02-08-2018, 12:17)
Aко са еквивалентни заявките, защо едната вади повече редове от другата, или си я пускал само в база с постове с nick = johnfound.

Двете заявки вадят абсолютно еднакъв краен резултат - 100 реда от постове написани от johnfound.

И не, разбира се, че не съм ги пускал на база с постове само от johnfound!

Пускал съм ги на работещата база на https://board.asm32.info защото там има SQL конзола за админа и ми е най-лесно.


--------------------
asm32 - Приложно програмиране на асемблер.
Tox: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9
PMEmail PosterUsers Website
Top
ldbl
Публикувано на: 02-08-2018, 11:55
Quote Post



Име: Станислав Неделчев
Група: Потребител
Ранг: Редовен член

Мнения: 357
Регистриран на: 22.09.07



Избяхването и на двете обикновенно се прави с напълно денормализирани таблици и се използва предимно в OLAP и бази даннни които са column oriented.И имат подходяши структури да се направи това. Но понякога не може без join, но както вече написах там пък идва проблем с паметта или други проблеми.
https://cloud.google.com/bigquery/docs/lega...nested-repeated

Това мнение е било редактирано от ldbl на 02-08-2018, 11:57


--------------------
PMEmail PosterUsers WebsiteICQ
Top
PxL
Публикувано на: 02-08-2018, 22:50
Quote Post


Group Icon
Име: Димитър Т. Димитров
Група: VIP
Ранг: Почетен член

Мнения: 2940
Регистриран на: 26.04.05



QUOTE (fast_user @ 02-08-2018, 12:17)
QUOTE (johnfound @ 01-08-2018, 23:41)
За да не съм голословен ето две еквивалентни заявки, едната с join другата с подзаявка (таблиците са от AsmBB защото това имам под ръка в момента):

CODE
select * from posts where userid = (select id from users where nick="johnfound");

select p.* from posts p left join users u on u.id = p.userid where nick = "johnfound";

Aко са еквивалентни заявките, защо едната вади повече редове от другата, или си я пускал само в база с постове с nick = johnfound.
Иначе да, ако не знаеш кога да ползваш inner и кога left, верно с подзаявки е по-добре.

Ти няк'ва микропишкова работа нямаш ли? Не се бутай в неща, от които нямаш представа. Ходи гледай клипове в YouTube.

Не, че ми дреме, но чета ти простите мнения и обикновено не им обръщам внимание, ама в някакъв момент почваш да дразниш.

Това мнение е било редактирано от PxL на 02-08-2018, 23:01


--------------------
void putchar(char c);int main(){int x,c=1,i;for(i=0;(x="PxLY2H4:2E;7231?=68255A5S5P9N:N9O84111H861I85111G9N:O811O812M<G33911EAEDBECE22169D1=2k"[i+++3]);)while(x-->'0')putchar((!(++c%'('))?0x0a:33^(i&1));}
PMEmail PosterUsers Website
Top
fast_user
Публикувано на: 03-08-2018, 00:30
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 583
Регистриран на: 19.09.12



Прати някой линк "Как да се извиняваме в мрежата", че откакто ползвам линукс, социалната ми неадекватност изригна и не знам как да общувам виртуално icon_sad.gif


--------------------
Linux is only free if your time has no value.
Linux Akbar
Чък Норис не използва Линукс, Линукс използва Чък Норис.
PMEmail Poster
Top
PxL
Публикувано на: 03-08-2018, 02:28
Quote Post


Group Icon
Име: Димитър Т. Димитров
Група: VIP
Ранг: Почетен член

Мнения: 2940
Регистриран на: 26.04.05



QUOTE (fast_user @ 03-08-2018, 01:30)
Прати някой линк "Как да се извиняваме в мрежата", че откакто ползвам линукс, социалната ми неадекватност изригна и не знам как да общувам виртуално  icon_sad.gif

Ето:
https://www.youtube.com/watch?v=VM-2OVNt-eQ

Дано не ти се насуче вратовръзката само.

Това мнение е било редактирано от PxL на 03-08-2018, 02:34


--------------------
void putchar(char c);int main(){int x,c=1,i;for(i=0;(x="PxLY2H4:2E;7231?=68255A5S5P9N:N9O84111H861I85111G9N:O811O812M<G33911EAEDBECE22169D1=2k"[i+++3]);)while(x-->'0')putchar((!(++c%'('))?0x0a:33^(i&1));}
PMEmail PosterUsers Website
Top
1 потребители преглеждат тази тема в момента (1 гости, 0 анонимни потребители)
Потребители, преглеждащи темата в момента:

Topic Options Страници: (3) 1 2 [3]  Reply to this topicStart new topicStart Poll

 


Copyright © 2003-2019 | BG Development | All Rights Reserved
RSS 2.0