Sziasztok,
Tudnátok segíteni? Miért lassú az alábbi MySQL parancs?
Többb mint 4 másodpercig fut egy modern gépen, ahol semmi más művelet nincs - többször futtatva is:
delete from table1 where column1 like 'pattern1%' and column2 in (select column3 from table2 where column4='pattern2')
table1 kb. 1100 recordot tartalmaz, ebből 95% a column1 / pattern1% találat.
table2 kb. 5000 recordot tartalmaz, ebből közel nulla a column4 / pattern2 találat.
Host: MySQL v5.7, Ubuntu 16 64 bit, gyors SSD, 1GB az InnoDB pool mem
Lehetne vajon a fentit egyszerűbben vagy gyorsabban? Köszönöm.
Szerk.: (kicsit olvashatóbb forma):
DELETE FROM t1 WHERE c1 LIKE 'p1%' AND c2 IN (SELECT c3 FROM t2 WHERE c4='p2')
Szerk2.: nem tudtom hogy ilyen gyorsan válaszoltok, amit köszönök, ezért indítottam ezelőtt egy SO fórum szálat is, beteszem ide, hátha segít:
http://stackoverflow.com/questions/40702486/mysql-delete-from-why-is-it…
Szerk.: Végül megoldottam index hozzáadásával a tábla2 column3 oszlopához, így nulla idő alatt fut.
- 1941 megtekintés
Hozzászólások
1. kérdés: ugyanez selectben, ami csak előállítja a kérdéses sorok id-ját, mennyi idő alatt fut le? (ugye ennél gyorsabb a delete sem tud lenni)
2. kérdés: ha elértük, hogy a select jó gyors legyen (a full table scan nem a barátja a gyors selectnek sem), és a delete még mindig lassú: hány sort szeretnél törölni? ha sokat, akkor az lassú lesz. az rdbms-ek már csak ilyenek...
- A hozzászóláshoz be kell jelentkezni
delete helyett select count(*) gyorsan lefut (~0 sec).
- A hozzászóláshoz be kell jelentkezni
Elso korben szerintem masolj be explain delete..., show create table
- A hozzászóláshoz be kell jelentkezni
Egyebkent szebb lenne join-ra atirva a query.
Meg talán gyorsabb is.
- A hozzászóláshoz be kell jelentkezni
Kaphatnék erre példát?
- A hozzászóláshoz be kell jelentkezni
Mármint hogy hogyan lehetne JOIN
-os?
- A hozzászóláshoz be kell jelentkezni
Igen. Lefuttatnám az exact példádat.
- A hozzászóláshoz be kell jelentkezni
Első felindulásra (tesztelés nélkül):
DELETE FROM table1
JOIN table2 ON (table1.column2=table2.column3 AND table2.column4='pattern2')
WHERE table1.column1 LIKE 'pattern1%'
A tévedés jogát természetesen fenntartom, szükség esetén blackluck kollega majd kijavít ;)
De hogy teljes legyen a kép, a "talán gyorsabb is"-ra forrás: mysql-doc, részlet:
A
LEFT [OUTER] JOIN
can be faster than an equivalent subquery because the server might be able to optimize it better
- A hozzászóláshoz be kell jelentkezni
Köszi, ma estig letesztelem és megírom.
- A hozzászóláshoz be kell jelentkezni
Szintax hiba van a kódodban és egyelőre nem találom hol:
"..syntax to use near 'JOIN..."
- A hozzászóláshoz be kell jelentkezni
Régen foglalkoztam már MySQL-lel "komolyabban", de itt, a "Multi-Table Deletes" rész alapján
DELETE table1 FROM table1
fog kelleni.
- A hozzászóláshoz be kell jelentkezni
Igen, így már jó, kösz.
Kicsivel lassabb az én eredeti megoldásomnál.
- A hozzászóláshoz be kell jelentkezni
explain delete...:
+----+--------------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | DELETE | table1 | NULL | ALL | NULL | NULL | NULL | NULL | 1179 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | table2 | NULL | ALL | NULL | NULL | NULL | NULL | 4601 | 1.00 | Using where |
+----+--------------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
show create table-ben semmit extra, utf8-as InnoDB pár oszloppal.
my.cnf custom része:
innodb_buffer_pool_size = 1G
query_cache_type = 1
- A hozzászóláshoz be kell jelentkezni
Nem látom alkalmas indexeket. Emiatt nem is használ...
- A hozzászóláshoz be kell jelentkezni
Ne csinalj ilyet.
DELETE FROM az csak IN (primary_key_value1, primary_key_value2, ...(stb.)) feltetellel toroljon tobb sort.
(UPDATE SET is ;) )
Mindenkepp csinalj elotte egy SELECT-et, foleg, ha LIKE query van, amin egy index se segit eleget. Egyeb esetben hosszu masodpercekre lelockolod az egesz tablat ezzel az egesz rendszert feltartva (a "mi mysql-unk" (5.6, Oracle-fele) legalabbis igy viselkedik).
Tehat:
1. query (nem lockol mert csak read):
SELECT DISTINCT table1_id FROM table1 where column1 like 'pattern1%' and column2 in (select column3 from table2 where column4='pattern2')
2. query:
DELETE FROM table1 WHERE table1_id IN ($vesszovelElvalasztvaElozoQueryEredmenyei)
(ez utobbi 10000-nel tobb sort ne toroljon, ugy mar tapasztalatom szerint tobbet arthat mint hasznal a sebessegnek.
- A hozzászóláshoz be kell jelentkezni
(Esetleg kiprobalhatod a tobbek kozt erre is alkalmas PHP-s tool-omat, ami meg nincs kesz, de ez a resze mar megbizhatoan mukodik:
https://github.com/dszakal/autodb
)
- A hozzászóláshoz be kell jelentkezni
Köszönöm az ajánlatodat, sajnos nincs mód a beillesztésre.
- A hozzászóláshoz be kell jelentkezni
AutoDb nelkul is megvan mondjuk 10-15 sorban amit eloszor javasoltam. A SELECT mint fentebb emlitettek akar gyorsabb is lehet JOINokkal, de nehez kontrollalni a MySQL-t, mert a query plan (EXPLAIN) read-only :(
(AutoDb libemben 3 sor amugy:
$autoDb = AutoDb::init($mysqli_object);
$rowsToDelete = $autoDb->rowsArray('tabla1', "column1 like 'pattern1%' and column2 in (select column3 from table2 where column4='pattern2')");
AutoRecord::deleteMore($rowsToDelete);
{Hol vannak a joinok? Joinokra egy masik (egyelore nem open) libemet hasznalom, leven a joinolt adat az nekem read only, vagy veszelyes vagy "irj sajat query-t, ugyis gyorsabb" kategorias}
)
- A hozzászóláshoz be kell jelentkezni
Köszi, de nem PHP fut a rendszeremen.
- A hozzászóláshoz be kell jelentkezni
Nincs primary key a táblákban.
- A hozzászóláshoz be kell jelentkezni
Composite primary key sincs? (Mondjuk az is soronkent torlest jelentene, vagy egy nagy kigeneralt (... AND ...) OR (... AND ...) tengert jelentene). Valami index amire lehet szukiteni, vagy valami amit nem csak LIKE-kal lehet query-zni es kelloen egyertelmu? Lenyeg hogy aminek a leggyorsabb a SELECT-je, azt add at a DELETE-nek.
for the future: MySQL-t meg nem javaslom PRIMARY KEY nelkul hasznalni. Nagyon nem. Lattam mar par query-t az elmult evekben, amit egy auto_incrementes (big)int PRIMARY KEY nelkul eselytelen lett volna olyan gyorsra meginrom amilyen gyorsan most fut. (EXPLAIN ugye read only, de PRIMARY KEY olvasast altalaban eloreveszi a rendszer)
- A hozzászóláshoz be kell jelentkezni
Egyelőre nem világos, hogy hol segítene nekem a primary key. A két tábla között nincs különösebb összefüggés logikailag, csak annyi hogy egy username bejegyzés ebben is van, meg a másikban is. De nem arra szűrök.
Köszönöm a javaslatokat.
- A hozzászóláshoz be kell jelentkezni
Millio ok van ra, pelda:
40 millio soros tabla, toroljunk mindent ami regebbi egy X datumnal (egyszeruseg kedveert limit 1000)
1. SELECT FROM
majd
2. DELETE IN (primary key-ek a SELECT-bol)
(vagy akar UPDATE)
Itt az 1-es query tobb masodperc, de csak read, nem lockol semmit. LIKE query eseten akar percekig is eltarthat a dolog
A 2-es meg nehany millisec (es csak arra a rovid idore lockolja a tablat, ergo a mogotte allo site mukodokepes marad).
Primary key nelkul ez egyetlen query - kenytelen vagy percekre lockolni a DB-t amig a DELETE FROM lefut
DELETE FROM WHERE ... LIKE ...
Az mar regen rossz ha ez utobbira ra vagy kenyszerulve, es az egesz alkalmazasban globalis lelassulast fog okozni. Es ez csak egyre rosszzabb lesz. Tedd be azokat a primary key-eket, amig 10000 sor alatt vannak a tablaid. Mondjuk kezdeskeppen mindenhova. :)
- A hozzászóláshoz be kell jelentkezni
Nem értem ennyiből. Tegyük fel beteszek minden táblámba primary key-t, megmutatnád hogy nézne ki a fenti query a te verziódban?
- A hozzászóláshoz be kell jelentkezni
c4-re van a vizsgálat, arra (is) kéne az index, nem?
Amúgy én az AND két felét is megfordítanám, a mostani második rész szelektívebb, célszerű azt előre rakni.
--
Gábriel Ákos
http://ixenit.com
- A hozzászóláshoz be kell jelentkezni
Megnézem, kösz.
- A hozzászóláshoz be kell jelentkezni