Ich habe eine große .sql
Datei voller SELECT
Anweisungen, die Daten enthalten, die ich in meine SQL Server-Datenbank einfügen möchte. Ich suche nach einer Möglichkeit, den Inhalt der Datei in 100 Zeilen gleichzeitig an die Befehle zu übergeben, die ich für den Rest festgelegt habe.
Grundsätzlich suche ich nach einer split
Ausgabe stdout
, nicht nach Dateien.
Ich verwende CygWin auch unter Windows, sodass ich nicht auf die gesamte Tool-Suite zugreifen kann.
shell
text-processing
stdout
split
Ehryk
quelle
quelle
BULK INSERT
? Trennen Sie die Daten von der SQL-Anweisung.Antworten:
Ich denke, der einfachste Weg, dies zu tun, ist:
Sie müssen
read
für die erste Zeile in jedem Abschnitt verwenden, da es anscheinend keine andere Möglichkeit gibt, anzuhalten, wenn das Ende der Datei erreicht ist. Weitere Informationen finden Sie unter:quelle
Die obige Funktion verwendet
sed
, um ihre Argumentliste als Befehlszeichenfolge auf ein beliebiges Zeileninkrement anzuwenden. Die Befehle, die Sie in der Befehlszeile angeben, werden in eine temporäre Shell-Funktion eingespeist, die ein Here-Dokument auf stdin erhält, das aus den Zeilenzeilen aller Inkremente besteht.Sie verwenden es so:
Der Mechanismus hier ist sehr einfach:
Das ist das
sed
Drehbuch. Grundsätzlich haben wir nurprintf $increment * n;
. Wenn Sie also Ihr Inkrement auf 100 setzenprintf
, erhalten Sie einsed
Skript, das aus 100 Zeilen besteht, die nur sagen$!n
, eineinsert
Zeile für das obere Ende des Here-Dokuments und eineappend
für die untere Zeile - fertig. Der größte Teil des Restes behandelt nur Optionen.Der
n
Befehl ext weist Siesed
an, die aktuelle Zeile zu drucken, zu löschen und die nächste zu ziehen. Das$!
gibt an, dass es nur eine Zeile außer der letzten versuchen soll.Vorausgesetzt, nur ein Inkrementierer wird es:
Was hier also hinter den Kulissen passiert, ist, dass die Funktion auf
echo
einen Zähler gesetzt undcat
dessen Eingabe erfolgt, wenn keine Befehlszeichenfolge angegeben wird. Wenn Sie es in der Befehlszeile sehen würden, würde es so aussehen:Es führt eine davon für jedes Inkrement aus. Aussehen:
WIRKLICH SCHNELL
Oben sage ich, dass es alle 4000 Zeilen erhöht werden soll. 17s später habe ich 20 Millionen Zeilen verarbeitet. Natürlich ist die Logik dort nicht ernst - wir lesen jede Zeile nur zweimal und zählen alle ihre Zeichen, aber die Möglichkeiten sind ziemlich offen. Auch wenn Sie genau hinschauen, werden Sie vielleicht bemerken, dass es anscheinend die Filter sind, die die Eingabe liefern, die sowieso die meiste Zeit in Anspruch nehmen.
quelle
dash
, undsed -f -
macht bsd sed auch nicht glücklich ... ganz zu schweigen davon, dass man die Heredoc-Marker zurück auf ^ ... ziehen mussGNU Parallel ist dafür gemacht:
Standardmäßig wird 1 Job pro CPU-Kern ausgeführt. Sie können die Ausführung eines einzelnen Jobs mit '-j1' erzwingen.
Die Version 20140422 enthält eine schnelle Version, die 3,5 GB / s liefern kann. Der Preis ist, dass es nicht die exakten 100 Zeilen liefern kann, aber wenn Sie die ungefähre Zeilenlänge kennen, können Sie --block auf das 100-fache einstellen (hier gehe ich davon aus, dass die Zeilenlänge nahe bei 500 Bytes liegt):
quelle
Am Ende hatte ich etwas, das scheinbar eklig ist. Wenn es einen besseren Weg gibt, poste es bitte:
Führen Sie aus,
./insert.sh "File.sql" 100
wobei die 100 die Anzahl der Zeilen ist, die gleichzeitig verarbeitet werden sollen.quelle
IFS= read -r line
. Betrachten Sie den Unterschied zwischenecho ' \t\e\s\t ' | { read line; echo "[$line]"; }
undecho ' \t\e\s\t ' | { IFS= read -r line; echo "[$line]"; }
. Auchecho
ist nicht sicher mit beliebigen Zeichenfolgen (zBline="-n"; echo "$line"
), es ist sicherer zu verwendenprintf '%s\n
.Wenn Sie Zugriff auf haben
gnu split
, führt die--filter
Option genau das aus:In Ihrem Fall können Sie diese Befehle also entweder mit
--filter
zoder schreiben Sie ein Skript, zB
myscript
:und dann einfach laufen
quelle