Python zrychlenie kódu

Python zrychlenie kódu
« kdy: 18. 01. 2021, 16:04:21 »
Zdravim akoby sa dalo zoptimalizovat toto? Mam cyklus kde pisem a citam data do 1.2s ale potreboval by som sa dostat pod 1.
Kód: [Vybrat]

for OPC_output in OPC_tag_list_output_array:
         value = '4:'
         tag_string = value + OPC_output
         #Load data from SQL
         SQL = "SELECT value FROM HMI.dbo.tag_list WHERE tag = '"+ OPC_output+"' "
         cursor.execute(SQL)
         result = cursor.fetchall()
         for row in result:
            SQL_Variable = row[0] 

             # Check if variable is string 
            OPC_Output_write = root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string])
           # print("before: ", OPC_Output_write.get_value())
         if (SQL_Variable[0] == '1') or (SQL_Variable[0] == '0'):
             # print (SQL_Variable)
              if SQL_Variable == '1':
                  SQL_Variable = True
              if SQL_Variable == '0':
                  SQL_Variable = False     
              Variable = SQL_Variable
              OPC_Output_write.set_value(ua.DataValue(ua.Variant(Variable, ua.VariantType.Boolean)))
         else: 
              String_var = ua.DataValue(ua.Variant(SQL_Variable, ua.VariantType.String))
              OPC_Output_write.set_value(String_var)                           
« Poslední změna: 18. 01. 2021, 16:15:28 od Petr Krčmář »


Re:Python zrychlenie kodu.
« Odpověď #1 kdy: 18. 01. 2021, 16:12:34 »
Zdravim akoby sa dalo zoptimalizovat toto? Mam cyklus kde pisem a citam data do 1.2s ale potreboval by som sa dostat pod 1.
Kód: [Vybrat]

for OPC_output in OPC_tag_list_output_array:
         SQL = "SELECT value FROM HMI.dbo.tag_list WHERE tag = '"+ OPC_output+"' "
So zrychlenim ti neviem pomoct, ale toto vyzera na solidny SQL Injection. Ak si zaciatocnik doporucujem si to vygoolit a pochopit, preco je to zle. Kazdopadne nikdy neskladaj SQL dotazy tak, ze SQL dotaz tvoris spajanim s uzivatelskym vstupom, to je velke nie.

Ad zrychlenie, vidim, ze tam iterujes cez vysledky, keby som to robil ja, snazil by som sa urobit co najkonkretnejsi SQL dotaz ktory mi vrati idealne jeden konkretny alebo co najmensiu mnozinu vysledkov a vsetky tieto operacie delegovat na databazu, tie uz byvaju optimalizovane na rychle dotazovanie.
« Poslední změna: 18. 01. 2021, 16:15:40 od nehalem »

Kit

  • *****
  • 568
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #2 kdy: 18. 01. 2021, 17:06:29 »
Co je zač ten objekt OPC_Output_write? Proč má tak divně pojmenované metody get_value() a set_value() a nemá třeba set_false(), set_true() a set_string()?

Nešlo by to celé udělat jedním trochu delším SQL dotazem?

Logik

  • *****
  • 854
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #3 kdy: 18. 01. 2021, 17:08:58 »
Nejprve si zjisti (pomocí profileru), co vlastně trvá dlouho. Databáze?
Pak pomocí
Kód: [Vybrat]
WHERE tag IN ( ...,...,...,....) ORDER by tag to načti z DB najednou a zpracovávej to v Pythonu.Pokud sql dotaz trvá dlouho, tak Ti asi taky schází index na políčku tag v databázi?

Ale jinak je ten kód podivnej, co je např.
Kód: [Vybrat]
OPC_Output_write = root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string]) To je nějaký lezení po stromě? Pak určitě se nemusí pokaždé lézt znovu z kořene, ne?

hechj

Re:Python zrychlenie kódu
« Odpověď #4 kdy: 18. 01. 2021, 17:49:12 »
Databáze by měla vrátit co nejkonkrétnější výsledek, v ideálním tvaru, abys nemusel dělat podmínky jestli je nula nebo jedna. Vypadá to dost pitomě. IN ti dotaz nezrychlí. Otázka na strom je zajímavá. Jestli ho máš v databázi, rychlejší by bylo procházet ho v sql


Kit

  • *****
  • 568
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #5 kdy: 18. 01. 2021, 18:19:19 »
Nejprve si zjisti (pomocí profileru), co vlastně trvá dlouho. Databáze?
Pak pomocí
Kód: [Vybrat]
WHERE tag IN ( ...,...,...,....) ORDER by tag to načti z DB najednou a zpracovávej to v Pythonu.

Že je IN ptákovinou, jsem zjistil po prvním benchmarku, ve kterém propadl.

Nejlepších výsledků jsem dosáhl, když jsem data nahrál do dočasné tabulky a provedl JOIN. Indexy zafungovaly a jelo to jako blesk.

Re:Python zrychlenie kódu
« Odpověď #6 kdy: 18. 01. 2021, 19:59:53 »
nehalem lebo nacitavam do toho hodnoty s pola tak vzdy s tej slucky do adresy pridavam nazov noveho tagu. K tomu SQL viem ale to budem riesit ak budem v poslednom kroku.

Hechj tam je problemv tom ze v databazy je vsetko varchar(255) a s tym nepohnem. PLC chce obcas Int, obcas String takze musim nacitavat vzdy "string" a obcas tam je len 0 a PLC chce True or False

Logik : nie je tam asi 5000 premennych a ja musim citat zapisovat len konkretnu. S tymto si presne adresujes.







Kit

  • *****
  • 568
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #7 kdy: 18. 01. 2021, 20:16:28 »
Co kdyby sis proměnnou OPC_tag_list_output_array uložil jako tabulku do databáze? Výstup všech hodnot získáš jedním dotazem.

Re:Python zrychlenie kódu
« Odpověď #8 kdy: 18. 01. 2021, 21:55:12 »
Kit ale ten array uz mam nacitany s configu. Takze to mi velmi nepomoze.
Este som zmenil
Kód: [Vybrat]
   result = cursor.fetchall()
         for row in result:
            SQL_Variable = row[0]
na
Kód: [Vybrat]
   SQL_Variable = cursor.fetchone()[0] ale to mi pridalo 10ms na cyklus a stale potrebujem zobrat 400.

Kit

  • *****
  • 568
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #9 kdy: 18. 01. 2021, 22:00:58 »
No tak to z configu nahrej do databázové tabulky. Bude to výrazně rychlejší.

Re:Python zrychlenie kódu
« Odpověď #10 kdy: 18. 01. 2021, 22:39:58 »
Kit nerozumiem. Ako to myslis?

Mam tam slucku
Kód: [Vybrat]
for OPC_output in OPC_tag_list_output_array:
OPC_tag_list_output_array je uz pole ktore som naplnil ked sa spusta program a ide v loope. Ako mi pomoze ked budem este extra citat data s databazy? Alebo ako to myslis?

Logik

  • *****
  • 854
    • Zobrazit profil
    • E-mail
Re:Python zrychlenie kódu
« Odpověď #11 kdy: 19. 01. 2021, 15:27:12 »
hejch:
Citace
. IN ti dotaz nezrychlí.
To bych se hádal. Načtění X záznamů z databáze najednou oproti načítání řádek po jednom zrychlí přístup do databáze v podstatě vždy. To je můj "denní chleba".

kit:
Citace
Že je IN ptákovinou, jsem zjistil po prvním benchmarku, ve kterém propadl.
Nejlepších výsledků jsem dosáhl, když jsem data nahrál do dočasné tabulky a provedl JOIN. Indexy zafungovaly a jelo to jako blesk.
Co já mám (s postrgresem) zkušenosti, tak hromadné načtení záznamů pomocí IN je vždy rychlejší, než načítání "po jednom", a nijak výkonnostně netrpí.Naházení do dočasné tabulky se dá udělat i jednodušeji pomocí
Kód: [Vybrat]
WITH data AS (
     VALUES (....),(...)
)
SELECT .....
ale nevidím důvod, proč by takovýto join měl proběhnout rychleji než operátor IN. Co jsem si teď zkusil na svejch malejch datech, tak IN byl rychlejší než JOIN (0.100-0.300ms versus 0.400-0.800ms), a lišili se i trochu v plánech (IN použil bitmap index scan, zatímco JOIN použil jen čistej index scan). Pokud jsem použil JOIN na temporary table, tak bez VACUUM ANALYZE na tu temporary table se použil sekvenční scan, po ANALYZE se použil stejnej plán, jako u JOINu na "WITH data AS ....".

Jaký výsledky a jaký plány to generuje Tobě?


Wangarg:
Citace
Kód: [Vybrat]
root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string])
nie je tam asi 5000 premennych a ja musim citat zapisovat len konkretnu. S tymto si presne adresujes.
No podstata mého dotazu je, že začátek tý adresace je vždy stejný, takže by to mělo jít znova použít. Navíc, nejde náhodou o todle?
https://github.com/FreeOpcUa/python-opcua/
Pokud ano, tak opravdu po stromě lezeš (jen to nevíš :-)), takže můžeš na začátku vyselektit ten 3:GlobalVars a pak už jen hledat ten podřízenej nod podle tagu. Ale třeba se pletu?