Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przyspiesz aktualizację MySQL/Insert Statement

Istnieje wiele problemów z wydajnością, jeśli musisz to zrobić miliony razy.

  • Przygotowujesz tę samą instrukcję SQL w kółko, miliony razy. Lepiej byłoby przygotować go raz i wykonać miliony razy.

  • Rozłączasz się z bazą danych przy każdym wywołaniu funkcji po jednym zapytaniu. Oznacza to, że za każdym razem musisz łączyć się ponownie, a wszelkie informacje z pamięci podręcznej są wyrzucane. Nie rób tego, pozostaw to podłączone.

  • Zobowiązujesz się po każdym rzędzie. To spowolni sprawę. Zamiast tego zatwierdź po wykonaniu partii.

  • Wybierz + aktualizacja lub wstaw prawdopodobnie można wykonać jako pojedynczy upsert.

  • To, że wstawiasz tak dużo do tabeli tymczasowej, prawdopodobnie ma problem z wydajnością.

  • Jeśli tabela ma zbyt wiele indeksów, które mogą spowolnić wstawianie. Czasami najlepiej jest usunąć indeksy, przeprowadzić dużą aktualizację zbiorczą i odtworzyć je.

  • Ponieważ umieszczasz wartości bezpośrednio w swoim SQL, Twój SQL jest otwarty na atak wstrzykiwania SQL .

Zamiast tego...

  • Użyj przygotowanych instrukcji i parametrów wiązania
  • Pozostaw bazę danych podłączoną
  • Dokonuj zbiorczych aktualizacji
  • Zatwierdzaj tylko pod koniec serii aktualizacji
  • Wykonaj całą matematykę w UPDATE zamiast SELECT + math + UPDATE .
  • Użyj „UPSERT” zamiast SELECT następnie UPDATE lub INSERT

Po pierwsze, przygotowane zestawienia. Pozwalają one MySQL raz skompilować instrukcję, a następnie ponownie ją wykorzystać. Pomysł polega na napisaniu oświadczenia z symbolami zastępczymi dla wartości.

select id, position, impressions, clicks, ctr
from temp
where profile_id=%s and
      keyword=%s and 
      landing_page=%s

Następnie wykonujesz to, używając wartości jako argumentów, a nie jako części ciągu.

self.cursor.execute(
   'select id, position, impressions, clicks, ctr from temp where profile_id=%s and keyword=%s and landing_page=%s',
   (profile_id, keyword, landing_page)
)

Dzięki temu baza danych może buforować przygotowaną instrukcję i nie musi za każdym razem jej ponownie kompilować. Pozwala również uniknąć ataku typu SQL injection, w którym sprytny atakujący może stworzyć wartość, która jest w rzeczywistości bardziej SQL, jak " MORE SQL HERE " . To bardzo, bardzo, bardzo powszechna luka w zabezpieczeniach.

Uwaga, może być konieczne użycie własnego MySQL Biblioteka bazy danych Pythona do uzyskiwania prawdziwych przygotowanych instrukcji . Nie przejmuj się tym zbytnio, używanie przygotowanych instrukcji nie jest twoim największym problemem z wydajnością.

Następnie to, co w zasadzie robisz, to dodawanie do istniejącego wiersza lub, jeśli nie ma istniejącego wiersza, wstawianie nowego. Można to zrobić wydajniej za pomocą pojedynczej instrukcji z UPSERT , połączony INSERT i UPDATE . MySQL ma to jako INSERT ... ON DUPLICATE KEY UPDATE .

Aby zobaczyć, jak to się robi, możemy napisać Twój SELECT then UPDATE jako pojedyncza UPDATE . Obliczenia są wykonywane w SQL.

    update temp
    set impressions = impressions + %s,
        clicks = clicks + %s,
        ctr = (ctr + %s / 2)
    where profile_id=%s and
          keyword=%s and
          landing_page=%s

Twoja INSERT pozostaje taka sama...

    insert into temp
        (profile_id, landing_page, keyword, position, impressions, clicks, ctr)
        values (%s, %s, %s, %s, %s, %s, %s)

Połącz je w jedną WSTAWIĆ O AKTUALIZACJI DUPLIKOWANEGO KLUCZA.

    insert into temp
        (profile_id, landing_page, keyword, position, impressions, clicks, ctr)
        values (%s, %s, %s, %s, %s, %s, %s)
    on duplicate key update
    update temp
    set impressions = impressions + %s,
        clicks = clicks + %s,
        ctr = (ctr + %s / 2)

Zależy to od definicji kluczy tabeli. Jeśli masz unique( profile_id, landing_page, keyword ) wtedy powinien działać tak samo jak twój kod.

Nawet jeśli nie możesz zrobić upsert, możesz wyeliminować SELECT próbując UPDATE , sprawdzając, czy coś zaktualizowało i czy nie wykonał INSERT .

Wykonuj aktualizacje zbiorczo. Zamiast wywoływać podprogram, który wykonuje jedną aktualizację i zatwierdza, przekaż mu dużą listę rzeczy do zaktualizowania i pracuj nad nimi w pętli. Możesz nawet skorzystać z executemany uruchomić tę samą instrukcję z wieloma wartościami. Następnie zatwierdź.

Możesz być w stanie wykonać UPSERT hurtowo. INSERT może zająć wiele rzędów na raz. Na przykład wstawia to trzy wiersze.

insert into whatever
    (foo, bar, baz)
values (1, 2, 3),
       (4, 5, 6), 
       (7, 8, 9)

Prawdopodobnie możesz zrobić to samo ze swoim INSERT ON DUPLICATE KEY UPDATE zmniejszenie narzutu na rozmowę z bazą danych. Zobacz ten post na przykład (w PHP, ale powinieneś być w stanie się dostosować).

Poświęca to zwracanie identyfikatora ostatniego wstawionego wiersza, ale to są przerwy.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. połączenie MATLAB 7.0 i MYSQL

  2. Integracja ssl z mysql - Odmowa dostępu

  3. Wyświetl wartość pojedynczej kolumny zapytania mysqli

  4. Oblicz deltę (różnicę bieżącego i poprzedniego wiersza) w sql

  5. Skuteczne ustalanie, czy firma jest otwarta, czy nie, na podstawie godzin pracy sklepu