baaaaardzo długie zapytanie, jak przyśpieszyć
Witam mam zapytanie wzięte z daemona z modułu payments. UPDATE documents SET closed = 1 WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0) AND type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0
ale to wykonuje się straaaasznie długo. na virtualce rzeźbi mi już 20minut i bez efektu :( da się to jakoś przyśpieszyć, z optymalizować?
mysql> select count(*) FROM cash; +----------+ | count(*) | +----------+ | 157215 | +----------+ 1 row in set (0.18 sec)
mysql> select count(*) FROM documents; +----------+ | count(*) | +----------+ | 111221 | +----------+ 1 row in set (0.09 sec)
podzapytanie: SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0 wykonuje się dosyć szybko i zwraca 876 rows in set (5.99 sec). wydaje mi się, że mając te podzapytanie update powinien się wykonać nie co szybciej.
da się z tym coś zrobić??
W dniu 2012-06-06 21:05, Marcin pisze:
Witam mam zapytanie wzięte z daemona z modułu payments. UPDATE documents SET closed = 1 WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time<= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value)>= 0) AND type IN (1, 3, 5) AND cdate<= unix_timestamp() AND closed = 0
ale to wykonuje się straaaasznie długo. na virtualce rzeźbi mi już 20minut i bez efektu :( da się to jakoś przyśpieszyć, z optymalizować?
mysql> select count(*) FROM cash; +----------+ | count(*) | +----------+ | 157215 | +----------+ 1 row in set (0.18 sec)
mysql> select count(*) FROM documents; +----------+ | count(*) | +----------+ | 111221 | +----------+ 1 row in set (0.09 sec)
podzapytanie: SELECT a.customerid FROM cash a WHERE a.time<= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value)>= 0 wykonuje się dosyć szybko i zwraca 876 rows in set (5.99 sec). wydaje mi się, że mając te podzapytanie update powinien się wykonać nie co szybciej.
da się z tym coś zrobić??
Pomnóż sobie czas wykonania tego zapytania * 111221 (pozycje w documents) i masz czas całości mniej-więcej. To zapytanie wykonuje się dla każdego rekordu który porównujesz. Jeżeli planujesz odpalać to częściej, stwórz sobie tablicę tymczasową, do której wrzuć wynik zapytania, i jej użyj.
W dniu 6 czerwca 2012 21:11 użytkownik Szymon Kajewski lysysoft@o2.plnapisał:
Pomnóż sobie czas wykonania tego zapytania * 111221 (pozycje w documents) i masz czas całości mniej-więcej. To zapytanie wykonuje się dla każdego rekordu który porównujesz. Jeżeli planujesz odpalać to częściej, stwórz sobie tablicę tymczasową, do której wrzuć wynik zapytania, i jej użyj.
dzięki za podpowiedz. racja, to zapytanie jest strasznie długie. jak zamiast podzapytania wstawiłem te 800 "wyników" to wykonało sie w mig.
podpowiedz, jak to wrzucić do tablicy tymczasowej?
W dniu 2012-06-06 21:15, Marcin pisze:
W dniu 6 czerwca 2012 21:11 użytkownik Szymon Kajewskilysysoft@o2.plnapisał:
Pomnóż sobie czas wykonania tego zapytania * 111221 (pozycje w documents) i masz czas całości mniej-więcej. To zapytanie wykonuje się dla każdego rekordu który porównujesz. Jeżeli planujesz odpalać to częściej, stwórz sobie tablicę tymczasową, do której wrzuć wynik zapytania, i jej użyj.
dzięki za podpowiedz. racja, to zapytanie jest strasznie długie. jak zamiast podzapytania wstawiłem te 800 "wyników" to wykonało sie w mig.
podpowiedz, jak to wrzucić do tablicy tymczasowej?
dla MySQL
CREATE TEMPORARY TABLE "table1temp" {Definicja}
INSERT INTO "table1temp" ("column1", "column2", ...) SELECT "column3", "column4", ... FROM "table2original"
Trzeba to jednak robić w jednym połączeniu, bo po zerwaniu połączenia tablica znika automatycznie.
On Wed, 06 Jun 2012 21:44:25 +0200, Szymon Kajewski wrote:
W dniu 2012-06-06 21:15, Marcin pisze:
W dniu 6 czerwca 2012 21:11 użytkownik Szymon Kajewskilysysoft@o2.plnapisał:
Pomnóż sobie czas wykonania tego zapytania * 111221 (pozycje w documents) i masz czas całości mniej-więcej. To zapytanie wykonuje się dla każdego rekordu który porównujesz. Jeżeli planujesz odpalać to częściej, stwórz sobie tablicę tymczasową, do której wrzuć wynik zapytania, i jej użyj.
dzięki za podpowiedz. racja, to zapytanie jest strasznie długie. jak zamiast podzapytania wstawiłem te 800 "wyników" to wykonało sie w mig.
podpowiedz, jak to wrzucić do tablicy tymczasowej?
dla MySQL
CREATE TEMPORARY TABLE "table1temp" {Definicja}
INSERT INTO "table1temp" ("column1", "column2", ...) SELECT "column3", "column4", ... FROM "table2original"
Trzeba to jednak robić w jednym połączeniu, bo po zerwaniu połączenia tablica znika automatycznie.
Pytanie z gatunku głupich - czemu nie utworzyć widoku?
W dniu 7 czerwca 2012 11:36 użytkownik Sarenka sarenka@mojasiec.comnapisał:
Pytanie z gatunku głupich - czemu nie utworzyć widoku?
nie znam się na mysql, ale czy czasem z widokiem nie będzie takiego samego efektu jak bez tabeli tymczasowej? czy czasem próbując dostać się do widoku nie jest wywoływany select kreujący ten widok?
W dniu 6 czerwca 2012 21:11 użytkownik Szymon Kajewski lysysoft@o2.plnapisał:
Jeżeli planujesz odpalać to częściej, stwórz sobie tablicę tymczasową, do której wrzuć wynik zapytania, i jej użyj.
już mam, dzięki wielkie.
mysql> create temporary table temp (a INT); Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO temp SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0; Query OK, 876 rows affected (1.53 sec) Records: 876 Duplicates: 0 Warnings: 0
mysql> UPDATE documents SET closed = 1 WHERE customerid IN (SELECT a from temp) AND type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0; Query OK, 0 rows affected (1.83 sec) Rows matched: 0 Changed: 0 Warnings: 0
jak widać w sumie <3s.
da się to w jednym zapytaniu zrobić?
2012/6/6 Marcin marcin@nicram.net
da się to w jednym zapytaniu zrobić?
Ok, mało ważne. da się zrobić po średnikach.
jeszcze raz Szymonie Wielkie dzięki za podpowiedź.
trzeba by uwzględnić również to w daemonie, bo to zapytanie właśnie z tamtąd.
On 06/06/2012 09:05 PM, Marcin wrote:
Witam mam zapytanie wzięte z daemona z modułu payments. UPDATE documents SET closed = 1 WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0) AND type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0
ale to wykonuje się straaaasznie długo. na virtualce rzeźbi mi już 20minut i bez efektu :( da się to jakoś przyśpieszyć, z optymalizować?
Dziwne. Jaki masz czas gdy zamienisz update na select?
SELECT id FROM documents WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0) AND type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0
Jaka wersja MySQLa?
2012/6/7 A.L.E.C alec@alec.pl
Dziwne. Jaki masz czas gdy zamienisz update na select?
SELECT id FROM documents WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time <= unix_timestamp() GROUP BY a.customerid HAVING SUM(a.value) >= 0) AND type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0
jak miałem rozliczone (przez poprzedni update) faktury to ten select
wykonał się szybko. przywróciłem bazę w której jest nie zamkniętych około 3000 faktur u prawie 900 klientów. to teraz ten select już długo kręci i nie przestaje; mysql> show processlist; +----+------+-----------+--------+---------+------+--------------+------------------------------------------------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+--------+---------+------+--------------+------------------------------------------------------------------------------------------------------+ | 44 | root | localhost | nicraM | Query | 675 | Sending data | SELECT id FROM documents WHERE customerid IN (SELECT a.customerid FROM cash a WHERE a.time <= unix_ | | 45 | root | localhost | NULL | Query | 0 | NULL | show processlist | +----+------+-----------+--------+---------+------+--------------+------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
a zestaw 3 zapytań: mysql> CREATE TEMPORARY TABLE tabela_tymczasowa AS SELECT customerid FROM cash WHERE time <= unix_timestamp() GROUP BY customerid HAVING SUM(value)
= 0;ALTER TABLE tabela_tymczasowa ADD UNIQUE (customerid);UPDATE documents
d RIGHT JOIN tabela_tymczasowa t ON t.customerid=d.customerid SET closed = 1 WHERE type IN (1, 3, 5) AND cdate <= unix_timestamp() AND closed = 0; Query OK, 876 rows affected (2.14 sec) Records: 876 Duplicates: 0 Warnings: 0
Query OK, 876 rows affected (0.03 sec) Records: 876 Duplicates: 0 Warnings: 0
Query OK, 2922 rows affected (0.30 sec) Rows matched: 2922 Changed: 2922 Warnings: 0
mysql>
jak widać różnica kolosalna.
Jaka wersja MySQLa?
mysql Ver 14.14 Distrib 5.1.49, for debian-linux-gnu jest to system do testów postawiony na virtualboxie na lapku.
uczestnicy (4)
-
A.L.E.C
-
Marcin
-
Sarenka
-
Szymon Kajewski