DoctorStrange ha scritto: ↑lunedì 2 ottobre 2023, 11:27
Fossi in te, valuterei anche un'alternativa. Cambia la sintassi della tua query di inserimento. Invece di
Codice: Seleziona tutto
INSERT INTO Tabella VALUES (val) (val) (val) (val) ...
Io proverei a riscriverla oin: [cpde]INSERT INTO Tabella (val);INSERT INTO Tabella (val);INSERT INTO Tabella (val);INSERT INTO Tabella (val);[/code]
Il motivo è semplice. In caso di interruzione della sessione con il server DB, con la tua sintassi, perderesti l'intero numero di record scritti e, nel caso di tre milioni di record da scrivere, non è una cosa trascurabile. Con questa variante invece, anche se potrebbe impiegare di piu, in caso di interruzione della sessione, i record già scritti rimarranno persistenti, e dovrai scrivere solo l'eventuale delta mancante.
Io davo per scontato che fosse questa la sintassi
Codice: Seleziona tutto
INSERT INTO Tabella (val);INSERT INTO Tabella (val);INSERT INTO Tabella (val);INSERT INTO Tabella (val);
e che
Codice: Seleziona tutto
INSERT INTO Tabella VALUES (val) (val) (val) (val) ...
fosse solo metacodice
Nel mio costrutto do' difatti una INSERT a ciclo, in cui inserisco un solo record per volta (con tutti i campi ovviamente).
....però, dopo ogni tot, lo script fa una pausa di riflessione per poi ripartire
Edit: questo è il mio codice in PowerShell da Windows, il server MySQL sta su una macchina linux (nei test fatti la macchina Windows è una vm che sta sullo stesso host dove risiede il server MySQL)
Codice: Seleziona tutto
# import the SimplySQL module
$ErrorActionPreference= 'Stop'
try {
Import-Module SimplySql
} catch {
Install-Module SimplySql -Confirm:$False -Force
Import-Module SimplySql
}
$ErrorActionPreference= 'Inquire'
# apro una connessione sul DB
Write-Host -NoNewline "Connecting... "
$ErrorActionPreference= 'Stop'
try {
Open-MySqlConnection -Server '192.168.xxx.yyy' -Database 'Miodb' -Credential $MySQLlogin
Write-Host -ForegroundColor Green 'DONE'
} catch {
Write-Host -ForegroundColor Red 'FAILED'
Write-Output "`nError: $($error[0].ToString())"
Pause
exit
}
$ErrorActionPreference= 'Inquire'
# raccolgo l'elenco delle tabelle presenti sul DB
$tablelist = Invoke-SqlQuery -Query 'SHOW TABLES'
# recupero la lista dei file e parso nonme tabella e data
foreach ($afile in (Get-ChildItem -Path ($sharepath + '\*.csv') -Name)) {
$matches = @()
$ErrorActionPreference= 'Stop'
try {
$afile -match "^([0-9]+)\-([a-zA-Z_\-\.\\\s0-9:]+)\.csv$" > $null
$uptime = [Datetime]::ParseExact($matches[1], 'yyMMdd', $null) | Get-Date -format "yyyy-MM-dd"
$tablename = $matches[2]
if ($tablelist.Tables_in_AGMskyline -contains $tablename) {
Write-Host -NoNewline -ForegroundColor Yellow ("Loading data for table [{0}] updated on {1}..." -f ($tablename, $uptime))
$ErrorActionPreference= 'Stop'
try {
# svuoto la tabella dei vecchi record
Invoke-SqlQuery -Query "TRUNCATE $tablename"
Write-Host -NoNewline -ForegroundColor Yellow '.'
# importo il csv di dati grezzi
Invoke-SqlQuery -Query "LOCK TABLES $tablename WRITE"
Write-Host -NoNewline -ForegroundColor Yellow '.'
$rawdata = Get-Content -Path ($sharepath + '\' + $afile)
$totrec = $rawdata.Count
$parsebar = ProgressBar
<# *** TESTING ***
Ho notato che il loop sulle query di INTRO, per ogni riga del csv, va un po' a rilento
sulle prime 10-20 query. Poi gira fluido con le righe rimanenti.
Potrebbe essere un problema di "buffering" legato al commit. Qui c'è la pagina di
riferimento di MySQL:
https://dev.mysql.com/doc/refman/8.0/en/innodb-autocommit-commit-rollback.html
Testare con cautela (aka vedere come gestire eventuali eccezioni su singole query errate
se il commit lo facessi alla fine del pacchetto intero di intro)
#>
for ($i = 0; $i -lt $rawdata.Count; $i++) {
$rawvalue = $rawdata[$i] -replace "'", "\'" # escaping single quote, see https://stackoverflow.com/questions/4803354/how-do-i-insert-a-special-character-such-as-into-mysql
$rawvalue = $rawvalue -replace '"', "'"
$rawvalue = $rawvalue -replace ';', ", "
Invoke-SqlQuery -Query "INSERT INTO $tablename VALUES ($rawvalue)"
Start-Sleep -Milliseconds 100
$rawvalue = $null
# progress
$percent = (($i) / $totrec)*100
if ($percent -gt 100) {
$percent = 100
}
$formattato = '{0:0.0}' -f $percent
[int32]$progress = $percent
$parsebar[2].Text = ("Add {0} out of {1} recs [{2}%] on {3}" -f (($i-1), $totrec, $formattato, $tablename))
if ($progress -ge 100) {
$parsebar[1].Value = 100
} else {
$parsebar[1].Value = $progress
}
[System.Windows.Forms.Application]::DoEvents()
}
$parsebar[0].Close()
Write-Host -NoNewline -ForegroundColor Yellow '.'
Invoke-SqlQuery -Query "UNLOCK TABLES"
Write-Host -NoNewline -ForegroundColor Yellow '.'
# aggiornamento update su UpdatedTables
Invoke-SqlQuery -Query "UPDATE `UpdatedTables` SET `UPDATED` = @atime WHERE `UpdatedTables`.`ATABLE` = @atable" -Parameters @{atime = $uptime; atable = $tablename}
Write-Host -NoNewline -ForegroundColor Yellow '.'
Write-Host -ForegroundColor Green 'DONE'
} catch {
Write-Host -ForegroundColor Red 'FAILED'
Write-Output "`nError: $($error[0].ToString())"
if ($rawvalue -ne $null) {
# faccio un check dell'eventuale riga del csv che possa aver sollevato un'eccezione durante una INSERT
Write-Host -ForegroundColor Blue "`n>>>$rawvalue<<<"
Pause
Invoke-SqlQuery -Query "UNLOCK TABLES"
} else {
Pause
exit
}
}
$ErrorActionPreference= 'Inquire'
} else {
Write-Host -ForegroundColor Red "Table [$tablename] not found on DB"
Pause
}
} catch {
Write-Host -ForegroundColor Red "Bad filename <$afile>"
# log x eccezioni non gestite, decommentare x debug
# Write-Output "Error: $($error[0].ToString())"
Pause
}
$ErrorActionPreference= 'Inquire'
}