Pitane
26 отговора
753 прегледа
Pitane
1. Kak se suzdavat 'Relationships' v MySQL mejdu tablitcite?
2. MySQL poddurja li vlojeni zaiavki?
3. А тригери и съхранени функции
2. MySQL poddurja li vlojeni zaiavki?
3. А тригери и съхранени функции
Re: Pitane
релациите са понятие от логическото моделиране и се създават като теглиш една черта (ползвай молив, не химикалка) между двете entities. От страната на детето чертата завършва с "пачи крак" или една дебела точка (в зависимост от нотацията която използваш).
Като настане време логическия модел да се напраи на физически вече не става дума за релации, а за форин кийс. С други думи в самата база данни релацията се реализира като форин кий.
Синтаксиса трябва да е нещо такова:
alter table <table name> add constraint <constraint name>
foreign key (column list) reference <parent table> (column list)
Смисълът е че в табле не можеш да имаш редове за които не съществъват съответните редове в парент табле.
Туй се нарича "declarative referential integrity" и в някой БД го има, в други го няма. В сайбейс например се появява чак във версия 10.
Ако няма декларативна интегрити, интегрити-то се прави с тригери. В самия тригер проверяваш дали родителя го има. И обратното -- като се изтрива/ упдейтва родителя се проверява дали има деца застрашени да останат сираци и или забраняваш операцията или първо изтриваш децата.
Ако БД няма и тригери, трябва защитаваш базата от данни чрез клиентската програма, което е загубена работа и трябва да се примириш с мисълта че лека-полека в базата ще се намърдат лайна, които трябва да се чистят, което хич не е приятно. Може разбира се да ги оставиш с надеждата че юзерите нямат толкова развито обоняние и няма да усетят миризмата.
В заключение, има един куп програми които подпомагат моделирането като налагат спазването на правилата за нормализация, рисуват диаграми на модела и в крайна сметка генерират скрипт с ДДЛ-ла на базата от данни. Препоръчвам горещо използването им за всеки проект, който изисква повече от 10 таблици. ErWin (CA) е готин, но има и сума ти други. Малко са скъпички, но за българина това не е проблем.

Като настане време логическия модел да се напраи на физически вече не става дума за релации, а за форин кийс. С други думи в самата база данни релацията се реализира като форин кий.
Синтаксиса трябва да е нещо такова:
alter table <table name> add constraint <constraint name>
foreign key (column list) reference <parent table> (column list)
Смисълът е че в табле не можеш да имаш редове за които не съществъват съответните редове в парент табле.
Туй се нарича "declarative referential integrity" и в някой БД го има, в други го няма. В сайбейс например се появява чак във версия 10.
Ако няма декларативна интегрити, интегрити-то се прави с тригери. В самия тригер проверяваш дали родителя го има. И обратното -- като се изтрива/ упдейтва родителя се проверява дали има деца застрашени да останат сираци и или забраняваш операцията или първо изтриваш децата.
Ако БД няма и тригери, трябва защитаваш базата от данни чрез клиентската програма, което е загубена работа и трябва да се примириш с мисълта че лека-полека в базата ще се намърдат лайна, които трябва да се чистят, което хич не е приятно. Може разбира се да ги оставиш с надеждата че юзерите нямат толкова развито обоняние и няма да усетят миризмата.
В заключение, има един куп програми които подпомагат моделирането като налагат спазването на правилата за нормализация, рисуват диаграми на модела и в крайна сметка генерират скрипт с ДДЛ-ла на базата от данни. Препоръчвам горещо използването им за всеки проект, който изисква повече от 10 таблици. ErWin (CA) е готин, но има и сума ти други. Малко са скъпички, но за българина това не е проблем.
Re: Pitane
>1. Kak se suzdavat 'Relationships' v MySQL mejdu tablitcite?
Ami wuobrazqwash si che gi ima kato kazwash sega klucha ot tqa tablica trqbwa da e sushtiq kato klucha ot drugata i pri selectetite go wzemash predwid. Nqma relni constrainti w MySQL
>2. MySQL poddurja li vlojeni zaiavki?
Ne, chak wuw versiq 5 t.e. sled 2-3 godini
>3. А тригери и съхранени функции
Pak sled 2-3 godini
Ami wuobrazqwash si che gi ima kato kazwash sega klucha ot tqa tablica trqbwa da e sushtiq kato klucha ot drugata i pri selectetite go wzemash predwid. Nqma relni constrainti w MySQL
>2. MySQL poddurja li vlojeni zaiavki?
Ne, chak wuw versiq 5 t.e. sled 2-3 godini
>3. А тригери и съхранени функции
Pak sled 2-3 godini
Re: Pitane
1. Както Бай Любо ти каза - на хартия. т.е. та "идейно ниво"
Ако те интересуват т-нар- FOREIGN KEYS - има ги за InnoDB таблици.
2. Във 4.1 и нагоре. ВЕЧЕ!!!
Само, че 4.1 е в много ранен стадий на разработка - още нямаме и Alpha.
Между другото непрекъснато се убеждавам, че в 90-95% от случаите когато някой пита за вложени заявки всъщност може и без тях. А по принцип когато нещо може и със и без ... без е по бързо поради голям ред причини и независимо от сървъра ... ама това е встрани от темата.
3. Съхранени Процезури в 5.0 - ако някой много силно се интересува ще му ги покажа работещи. Има много време обаче.
Тригери - планирани са за 5.0
Съвсем логично е защото едва ли някой може да си представи смисъл от Тригери без Съхранени Процедури
salle.online.bg/sig
Ако те интересуват т-нар- FOREIGN KEYS - има ги за InnoDB таблици.
2. Във 4.1 и нагоре. ВЕЧЕ!!!
Между другото непрекъснато се убеждавам, че в 90-95% от случаите когато някой пита за вложени заявки всъщност може и без тях. А по принцип когато нещо може и със и без ... без е по бързо поради голям ред причини и независимо от сървъра ... ама това е встрани от темата.
3. Съхранени Процезури в 5.0 - ако някой много силно се интересува ще му ги покажа работещи. Има много време обаче.
Тригери - планирани са за 5.0
Съвсем логично е защото едва ли някой може да си представи смисъл от Тригери без Съхранени Процедури
salle.online.bg/sig
Re: Павеле...къде четеш?
> Ne, chak wuw versiq 5 t.e. sled 2-3 godini
mysql> select version();
+-----------------------+
| version() |
+-----------------------+
| 4.1.0-alpha-debug-log |
+-----------------------+
1 row in set (0.02 sec)
mysql> select a from t1 where a in (select a from t1 where a in (select b from t2));
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
mysql> explain select a from t1 where a in (select a from t1 where a in (select b
from t2));
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
| 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 2 | DEPENDENT SUBSELECT | t1 | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 3 | DEPENDENT SUBSELECT | t2 | system | NULL | NULL | NULL | NULL | 1 | |
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
3.
> Pak sled 2-3 godini
mysql> select version();
+-------------------+
| version() |
+-------------------+
| 5.0.0-alpha-debug |
+-------------------+
1 row in set (0.02 sec)
Има работещи съхранени процедури така, че се надявам и тук да не си прав за 2-3 те години

salle.online.bg/sig
mysql> select version();
+-----------------------+
| version() |
+-----------------------+
| 4.1.0-alpha-debug-log |
+-----------------------+
1 row in set (0.02 sec)
mysql> select a from t1 where a in (select a from t1 where a in (select b from t2));
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
mysql> explain select a from t1 where a in (select a from t1 where a in (select b
from t2));
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
| 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 2 | DEPENDENT SUBSELECT | t1 | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 3 | DEPENDENT SUBSELECT | t2 | system | NULL | NULL | NULL | NULL | 1 | |
+----+---------------------+-------+--------+---------------+------+---------+------+------+-------------+
3.
> Pak sled 2-3 godini
mysql> select version();
+-------------------+
| version() |
+-------------------+
| 5.0.0-alpha-debug |
+-------------------+
1 row in set (0.02 sec)
Има работещи съхранени процедури така, че се надявам и тук да не си прав за 2-3 те години
salle.online.bg/sig
тук пак може да заспорим....
А по принцип когато нещо може и със и без ... без е по бързо поради голям ред причини и независимо от сървъра ... ама това е встрани от темата.
я кажи една причина поне ?
ако говорим за това, че една добре оптимизирана заявка се изпълнява по-бързо и създава по-малко грижи на сървъра - съгласен!!!
но аз мисля, че е точно обратното - когато може без и със... обикновено по бързо е със!
[линк]
я кажи една причина поне ?
ако говорим за това, че една добре оптимизирана заявка се изпълнява по-бързо и създава по-малко грижи на сървъра - съгласен!!!
но аз мисля, че е точно обратното - когато може без и със... обикновено по бързо е със!
[линк]
Re: Pitane
Che za kakvo mi e togava tozi MySQL. Niakoi moje li da me ubedi v tova da go izpolzvam?
Re: Pitane
Ползвай IB6/Firebird
Има всичко горепосочено + транзакции (salle ще ти каже, че и те ги имат понякога, но обикновено не били необходими
)
По-безплатен е
Айде на войната-а-а-а
Има всичко горепосочено + транзакции (salle ще ти каже, че и те ги имат понякога, но обикновено не били необходими
По-безплатен е
Айде на войната-а-а-а
Re: Pitane
Ако ти трябват точно тези неща който липсват в който и да е продукт никой в нищо не може да те убеди естествено.
Иначе мога да ти посоча много причини, но все пак по-добре потършувай из интернета за да провериш защо толкова милиони потребители харесват MySQL
salle.online.bg/sig
Иначе мога да ти посоча много причини, но все пак по-добре потършувай из интернета за да провериш защо толкова милиони потребители харесват MySQL
salle.online.bg/sig
Re: Pitane
Spored men MySQL e edna skupena versia na SQL Server, po tova koeto vijdam. Chudno mi e kato se razvie i stane sushtoto durvo kato SQL Server -a dali pak shte go haresvat???
Re: за какво?
Това което твърдя, е че ако една заявка може да бъде написанана по два начина със и без вложени SELECT то първия начин в общия случай (почти винаги) ще е по-бърз.
Пример
select t1.id from t1 where id in (select id from t2);
select t1.id from t1, t2 where t1.id = t2.id;
Двете заявки връщат идентичен резултат. Само, че при първата Сървъра трябва да направи следното:
select id from t2;
т.е. да избере стойностите на id за всички редове от таблилца t2
да ги запомни в някаква временна таблица и след това да сравнява стойностите от t1 с тези от временната таблица.
Колкото и да е хитър оптимизатора просто в този случай има да свърши повече работа отколкото при Join-а във втората заявка където може да претърси за съвпадащи стойности във Индексите на двете таблици (предполагайки, че ID са индексирани и в двете)
Да не говорим за вложени заявки, които се обръщат към "обвиващата" заявка - там много лесно можеш да накараш сървръа за таблици
t1 -> 1M реда
t2 -> 10 000 реда
да изпълни по 1 заявка върху t2 за всеки ред от t1 - т.е. 1 милион + 1 заявки върху талбица t2
вместо JOIN, който "закача" t2 само веднъж.
Изобщо не случайно в доста книги за SQL съветват да се избягват всякакви вложени заявки освен когато няма друг начин да се реши проблема.
Тъй, че това е моето твърдение - за идентичен резултат решението с вложени заявки е по-бавно на всеки сървър. Понякога драстично по-бавно.
Демонстрирай ми поне един пример къдетопри дДОБРЕ ОБМИСЛЕНИ ИНДЕКСИ и ДОБРЕ ОПТИМИЗИРАН SQL с вложени заявки работи по-бързо от ДОБРЕ ОПТИМИЗИРАН SQL без вложени заявки като и двата връщат идентичен резултат.
Подчертавам оптимизацията защото винаги можеш да направиш контрапример от рода на "да ама когато в таблиците няма никакви индекси ...."
salle.online.bg/sig
Пример
select t1.id from t1 where id in (select id from t2);
select t1.id from t1, t2 where t1.id = t2.id;
Двете заявки връщат идентичен резултат. Само, че при първата Сървъра трябва да направи следното:
select id from t2;
т.е. да избере стойностите на id за всички редове от таблилца t2
да ги запомни в някаква временна таблица и след това да сравнява стойностите от t1 с тези от временната таблица.
Колкото и да е хитър оптимизатора просто в този случай има да свърши повече работа отколкото при Join-а във втората заявка където може да претърси за съвпадащи стойности във Индексите на двете таблици (предполагайки, че ID са индексирани и в двете)
Да не говорим за вложени заявки, които се обръщат към "обвиващата" заявка - там много лесно можеш да накараш сървръа за таблици
t1 -> 1M реда
t2 -> 10 000 реда
да изпълни по 1 заявка върху t2 за всеки ред от t1 - т.е. 1 милион + 1 заявки върху талбица t2
вместо JOIN, който "закача" t2 само веднъж.
Изобщо не случайно в доста книги за SQL съветват да се избягват всякакви вложени заявки освен когато няма друг начин да се реши проблема.
Тъй, че това е моето твърдение - за идентичен резултат решението с вложени заявки е по-бавно на всеки сървър. Понякога драстично по-бавно.
Демонстрирай ми поне един пример къдетопри дДОБРЕ ОБМИСЛЕНИ ИНДЕКСИ и ДОБРЕ ОПТИМИЗИРАН SQL с вложени заявки работи по-бързо от ДОБРЕ ОПТИМИЗИРАН SQL без вложени заявки като и двата връщат идентичен резултат.
Подчертавам оптимизацията защото винаги можеш да направиш контрапример от рода на "да ама когато в таблиците няма никакви индекси ...."
salle.online.bg/sig
Re: Pitane
MySQL Е SQL Server :)
Както и Oracle, DB2, Interbase, PostgreSQL и т.н. и т.н. Доста играчи са на този пазар
Няма нужда да чакаш бъдещето.
И сега много повече потребители предпочитат MySQL пред останалите SQL Server-и
Което разбира се не означава, че си длъжен да се съобразяваш с тях.
А какво ще стане за в бъдеще ...
Всъщност за какво изобщо продължаваш тази тема?
salle.online.bg/sig
Както и Oracle, DB2, Interbase, PostgreSQL и т.н. и т.н. Доста играчи са на този пазар
Няма нужда да чакаш бъдещето.
И сега много повече потребители предпочитат MySQL пред останалите SQL Server-и
Което разбира се не означава, че си длъжен да се съобразяваш с тях.
А какво ще стане за в бъдеще ...
Всъщност за какво изобщо продължаваш тази тема?
salle.online.bg/sig
Редактирано от salle на
Re: тук пак може да заспорим....
аз лично само веднъж съм виждал subselect да работи по-бързо от join и то, защото join-а успява да прави същото нещо като по-чудо (а бе не ми се обяснява)
ама като цяло твърдението, че subselect е по-бързо !! ми се струва леко казано абсурдно
ама като цяло твърдението, че subselect е по-бързо !! ми се струва леко казано абсурдно
Re: Pitane
доста абсурдно изказване
mysql изобщо няма нищо общо с SQL Server (ако под това визираш microsoft-ския) и ще ти служи перфектно за някои цели (твоите ти не си ги споделил, така че конкретно не може да се каже)
но иначе
1. лесно се работи
2. бърз
3. и free, ако искаш може да си платиш съпорт
(липсата на subselects в повечето случаи ще те накара да помислиш по-свястно решение, така че не винаги това е минус)
mysql изобщо няма нищо общо с SQL Server (ако под това визираш microsoft-ския) и ще ти служи перфектно за някои цели (твоите ти не си ги споделил, така че конкретно не може да се каже)
но иначе
1. лесно се работи
2. бърз
3. и free, ако искаш може да си платиш съпорт
(липсата на subselects в повечето случаи ще те накара да помислиш по-свястно решение, така че не винаги това е минус)
Колко е хитър оптимизатора
Някои са много хитри. Сайбейз (и мс сял сержер) при първа възможност сплескват събкуирито в джоин -- т.е. преписват заявката като джоин и тогава я изпълняват. Това обаче не всякога е възможно. В примера който си дал събкуирити и джойна не са винаги еквивалентни, а само когато има взаимно еднозначно съответстви м/у двете таблици. Ето ти и контрапример:
print "sybquery:"
select first_name, last_name from person_name
where f_prsn_index_num in (
select index_num from person where birth_date="Jan 13, 1972"
)
go
print "join:"
select first_name, last_name from
person_name a, person b
where b.index_num=a.f_prsn_index_num
and b.birth_date="Jan 13, 1972"
go
sybquery:
first_name last_name
------------------------- ----------------------------------------
Fawzi JAMES
David JACQUOT
Jaime Martel
Jaime Martel
(4 rows affected)
Table: person_name scan count 3, logical reads: (regular=13 apf=0 total=13),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Table: person scan count 1, logical reads: (regular=12848 apf=0 total=12848),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Total writes for this command: 0
join:
first_name last_name
------------------------- ----------------------------------------
Fawzi JAMES
David JACQUOT
Jaime Martel
Jaime Martel
Jaime Martel
Jaime Martel
(6 rows affected)
Table: person_name scan count 4, logical reads: (regular=17 apf=0 total=17),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Table: person scan count 1, logical reads: (regular=12848 apf=0 total=12848),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Total writes for this command: 0
Както виждаш джойна връща 2 реда повече щото Джайме Мартел има 4 реда в персон, но само два в персон_наме.
Освен това, както личи от статистиките събкуирито е със 4 страници по-ефтино от джойна -- пренебрежимо малко, но все пак.
print "sybquery:"
select first_name, last_name from person_name
where f_prsn_index_num in (
select index_num from person where birth_date="Jan 13, 1972"
)
go
print "join:"
select first_name, last_name from
person_name a, person b
where b.index_num=a.f_prsn_index_num
and b.birth_date="Jan 13, 1972"
go
sybquery:
first_name last_name
------------------------- ----------------------------------------
Fawzi JAMES
David JACQUOT
Jaime Martel
Jaime Martel
(4 rows affected)
Table: person_name scan count 3, logical reads: (regular=13 apf=0 total=13),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Table: person scan count 1, logical reads: (regular=12848 apf=0 total=12848),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Total writes for this command: 0
join:
first_name last_name
------------------------- ----------------------------------------
Fawzi JAMES
David JACQUOT
Jaime Martel
Jaime Martel
Jaime Martel
Jaime Martel
(6 rows affected)
Table: person_name scan count 4, logical reads: (regular=17 apf=0 total=17),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Table: person scan count 1, logical reads: (regular=12848 apf=0 total=12848),
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
Total writes for this command: 0
Както виждаш джойна връща 2 реда повече щото Джайме Мартел има 4 реда в персон, но само два в персон_наме.
Освен това, както личи от статистиките събкуирито е със 4 страници по-ефтино от джойна -- пренебрежимо малко, но все пак.
Re: за какво?
Има и още един вид вложени заявки (не знам дали MySQL ги поддържа) и това са тези завки които имад вложени заявки в select клаузата. Например:
select (select t2.col1 from table2 t2 t2.id = t1.id) from table1 t1
В някои случаи (особено при големи обеми в table2 и ако t2.id е primary key) тази заявка може да се изпълни доста по бързо от join. Да не говорим за по сложните случаи, в които съм виждал ако се използва подобрен подход скоростта да се увеличава с пъти.
Боже колко мъка има на този свят Боже!



select (select t2.col1 from table2 t2 t2.id = t1.id) from table1 t1
В някои случаи (особено при големи обеми в table2 и ако t2.id е primary key) тази заявка може да се изпълни доста по бързо от join. Да не говорим за по сложните случаи, в които съм виждал ако се използва подобрен подход скоростта да се увеличава с пъти.
Боже колко мъка има на този свят Боже!
Re: а защо не знаеш? :)
> Има и още един вид вложени заявки (не знам дали MySQL ги поддържа)
Ми то си пише. Със всеки MySQL вкл. и кода на 4.1 пристига тест пакета. Та там има една колекция от вложени заявки и някои от тях изглеждат ей така:
select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
Е някои са доста специфични за MySQL ама има хора които много ще им се зарадват:
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order
by a limit 2) limit 3;
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where
t4.b=(select max(t2.a)*4 from t2) order by a);
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
Има и такива които честно казана предпочитам никога да не ги виждам от рода на:
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
И така нататък. Изобщо идеята е преди 4.1 да стане beta да поддържа всеки възможен синтаксис на вложени заявки според SQL99
salle.online.bg/sig
Ми то си пише. Със всеки MySQL вкл. и кода на 4.1 пристига тест пакета. Та там има една колекция от вложени заявки и някои от тях изглеждат ей така:
select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
Е някои са доста специфични за MySQL ама има хора които много ще им се зарадват:
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order
by a limit 2) limit 3;
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where
t4.b=(select max(t2.a)*4 from t2) order by a);
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
Има и такива които честно казана предпочитам никога да не ги виждам от рода на:
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
И така нататък. Изобщо идеята е преди 4.1 да стане beta да поддържа всеки възможен синтаксис на вложени заявки според SQL99
salle.online.bg/sig