Laden...

Forenbeiträge von Exception234 Ingesamt 10 Beiträge

17.12.2020 - 09:55 Uhr

Dann wäre aber noch die Frage, was für eine Anwendung du hier hast.
Ist dies eine Web oder Desktop Anwendung?
Auch wäre wichtig welche Art von Daten du in den Tabellen speicherst?
Ggf. gibt es einen anderen Ansatz als einen lokalen DB Server?

T-Virus

Die Struktur ist fix vorgegeben. Es sind einfache Statusinfos, die täglich von anderen Systemen aufgezeichnet werden. Bei Anbindung neuer Quellen besteht jeodch die Möglichkeit dass einmalig große Mengen anfallen.

Bulk-Inserts werden unterstützt:

INSERT INTO table_name (column_list)
VALUES
(value_list_1),
(value_list_2),
...
(value_list_n);

mmh ja das geht. Ich rede hier wohl von was anderem 😦 Microsoft bietet die Klasse SqlBulkCopy („Ermöglicht den effizienten Massenladevorgang einer SQL Server-Tabelle mit Daten aus einer anderen Quelle.“) Hierzu hab ich kein MySQL Äquivalent gefunden.
Die Annahme war, dass es sich bei dem SQL Befehl LOAD DATA LOCAL INFILE '<filepath>' INTO TABLE <table> genau darum handelt. Damit sollte bei Verwendung in einer Transaktion bereits ein Transaktionslogeintrag vorhanden sein der besser aufbereitet ist ... hab ich aber noch nicht getestet.

16.12.2020 - 16:39 Uhr

Ja aber Hardwarebeschaffung is ne andere Kostenstelle – kennst du bestimmt 😃 Ich hab ja gezielt nach stabilen Inserts gefragt und bin an sich richtig dankbar über die schwache Platte. Mir wäre die Fehleranfälligkeit sonst nie aufgefallen. Da das gern ewig laufen darf geht mir Stabi über Performance. Wenn der Performance-Wunsch nachher kommt, ist auslagern ne feine Sache ohne das Code angepasst werden muss. Das schöne ist, dass man den Flaschenhals beim Schreiben im Taskmanager eindeutig sieht ... und hören tu ich ihn unterm Tisch auch 😃

16.12.2020 - 15:17 Uhr

Danke euch – mit der Erläuterung zur Nachbereitung von Transaktionslog und Dirtypages ist nun klar was da blockiert. Gemäß my.ini wird das nach jedem Commit gemacht … passt auch exakt zum Verhalten.

[client]
port=3306
[mysql]
no-beep
[mysqld]
datadir=C:/ProgramData/MySQL/MySQL Server 8.0\Data
sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"
log-output=FILE
general-log=0
general_log_file="DREPC0595.log"
slow-query-log=1
slow_query_log_file="DREPC0595-slow.log"
long_query_time=10
log-error="DREPC0595.err"
log-bin="DREPC0595-bin"
server-id=1
lower_case_table_names=1
secure-file-priv="C:/ProgramData/MySQL/MySQL Server 8.0/Uploads"
max_connections=151
table_open_cache=2000
tmp_table_size=135M
thread_cache_size=10
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=259M
key_buffer_size=8M
read_buffer_size=64K
read_rnd_buffer_size=256K
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=1M
innodb_buffer_pool_size=8M
innodb_log_file_size=48M
innodb_thread_concurrency=17
innodb_autoextend_increment=64
innodb_buffer_pool_instances=8
innodb_concurrency_tickets=5000
innodb_old_blocks_time=1000
innodb_open_files=300
innodb_stats_on_metadata=0
innodb_file_per_table=1
innodb_checksum_algorithm=0
back_log=80
flush_time=0
join_buffer_size=256K
max_allowed_packet=4M
max_connect_errors=100
open_files_limit=4161
sort_buffer_size=256K
table_definition_cache=1400
binlog_row_event_max_size=8K
sync_master_info=10000
sync_relay_log=10000
sync_relay_log_info=10000
loose_mysqlx_port=33060

Bulk-Inserts werden unter MySQL scheinbar nicht so unterstützt wie von MS SQL Server. Wenn ich es richtig verstehe basiert das Ganze auf fileinput. Da das auch wieder IO lastig ist, würde es das Problem nur verlagern. Falls sich SQL Statement:

LOAD DATA LOCAL INFILE '<filepath>' INTO TABLE <table>

auch mit einem gepufferten file ausfüren lässt, würde ich die Variante in die engere Auswahl nehmen. Negativ ist, dass die Ausführung an Bedingungen geknüpft ist.

Error Code: 3948. Loading local data is disabled; this must be enabled on both the client and server sides. 

Bei späterem Nichtbeachten käme es zu Ausfällen.

In jedem Fall würde die Behandlung eines von der Platte verschuldeten TimeOut dann aber so ausschauen, den betroffenen Commit beim Neuversuch solange zu verzögern bis wieder Ressourcen vorhanden sind

15.12.2020 - 20:18 Uhr

Auweh - danke für den Hinweis mit Bulk.
Kannte ich bisher leider nicht. Das das passe ich noch an.

Aber das eigentliche Problem ist ja, das ein einzelner commit wohl asynchron weiterläuft und die Platte so belastet wird bis ein Folgecommit den timeout wirft. Ich würde in dem Fall gerne solange warten bis ein Schreiben wieder sicher möglich ist und die Befüllung sauber zu Ende läuft. Lässt sich hier ein Event abfragen oder bin ich auf nem völlig falschen Dampfer?

15.12.2020 - 15:11 Uhr

verwendetes Datenbanksystem: <MySQL>

Huhu, ich befülle parallel 2 Tabellen. Plan war die Insert Statements dafür solange aufzubauen bis sie in den Bereich der max_allowed_packet Größe kommt ... dann die beiden Executes abfeuern und einmal commiten.
Dann wieder von vorn bis alle Insert Statements weggeschrieben sind.
Dabei passiert was doofes. Mein Platte arbeitet nach den ersten paar Commits am Limit (jetzt ned lachen ... 1,4 MB/s) und kommt mit der Abarbeitung der Folge-Commits nicht nach. Irgendwann meldet die DB dann nen Timeout.

Hat vielleicht jemand einen Vorschlag, der den nächsten Commit erst losschickt, wenn der vorherige komplett abgearbeitet ist? Die zusammengehörigen Inserts der beiden Tabellen sollten dabei zeitgleich commitet werden. Ich hab akt. das so gelöst …


using MySql.Data.MySqlClient;

using (MySqlConnection con = new MySqlConnection(myConnString))
{
   con.Open();
   foreach(Element element in Elmements)
   {
      //fill string statement_tab1
      //fill string statement_tab2               

      if ((bytesInStatement > (max_allowed_packet/100)) || lastStatement)          
      {                       
         DateTime starttime = DateTime.Now;                      
         using (MySqlTransaction trans = con.BeginTransaction())
         {
            using (MySqlCommand cmd1 = new MySqlCommand(statement_tab1, con))
            {
               cmd1.Transaction = trans;
               cmd1.CommandType = CommandType.Text;
               cmd1.ExecuteNonQuery();                                                              
            }                           
            using (MySqlCommand cmd2 = new MySqlCommand(statement_tab2, con))
            {
                cmd2.Transaction = trans;
                cmd2.CommandType = CommandType.Text;
                cmd2.ExecuteNonQuery();                               
            }
            trans.Commit();

            DateTime endtime = DateTime.Now;
            double timespan = (DateTime.Now - starttime).TotalSeconds;                          
            Console.WriteLine(statementsize + " bytes in " + timespan.ToString("0.00")  + " seconds");
         }
         statement_tab1 = string.Empty;
         statement_tab2 = string.Empty;
         bytesInStatement = 0;
      }
   }  
   con.Close();
}


Danke euch

21.10.2020 - 14:30 Uhr

Klingt vernünftig. Die Varianten schau ich mir mal an. 300MB sollte die Grenze sein - da wäre noch viel Luft zu deinem Wert. Danke

21.10.2020 - 12:54 Uhr

Achso: Das tatsächliche Object ist recht groß und ich brauche nur sehr wenig vom Inhalt. Ich hatte auf performante Boardmittel von JSON gehofft um gezielt zu navigieren

21.10.2020 - 11:25 Uhr

Huhu,

ich nutze Newtonsoft.Json um den content der customfields aus folgendem Object zu ermitteln:

total	"2"
issues	
 0	
  id	"1"
  fields	
   customfield_1	"one"
   customfield_2
    value:          "one"
    id:             "1"
 1	
  id	"2"
  fields	
   customfield_1	"two"
   customfield_2
    value:          "two"
    id:             "2"

Es fehlt jedoch eine Möglichkeit verschachtelte Schlüssel auf Existenz abzufragen. Z.B. so

Object.ContainsKey("total"));

Die Klasse JObject bietet die Möglichkeit nur für Schlüssel in erster Ebene. JToken scheinbar gar nicht. Meine Codevariante funktioniert leider nicht.

if (jObject["issues"] != null)
{
	foreach (JToken issue in jObject["issues"])
	{
		if (issue["fields"] != null)
        {
			foreach (string customfield in myCustomfields)
			{
				if (issue["fields"][customfield] != null)
				{
					if (issue["fields"][customfield]["id"] != null)
					{
                        //get content                  
					}
					if (issue["fields"][customfield]["value"] != null)
					{
                         //get content              
					}
				}
			}			
		}
	}
}

Bliebe noch die Möglichkeit mit String Operationen drauf los zugehen ... weiß jemand, ob es auch eleganter funktioniert?

Danke Euch

07.10.2020 - 17:05 Uhr

Danke dir Abt ... künftig nur noch HttpClient 😃


static HttpClient GetClient(string username, string password)
{
   AuthenticationHeaderValue authValue = new AuthenticationHeaderValue
   ("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")));

   HttpClient client = new HttpClient()
   {
       DefaultRequestHeaders = { Authorization = authValue }
   };
    return client;
}

async Task request()
{
   HttpClient client = GetClient(connection.username, connection.password);
   string response = await client.GetStringAsync("https://myserver/rest/api/2/search?jql=status%20=%20Open&maxResults=0");
   Console.WriteLine(response);
}

28.09.2020 - 14:07 Uhr

Huhu, hat hier jemand nen kleinen Tipp?

die Browseranfrage (FireFox,Edge) https://myserver/rest/api/2/search?jql=status%20=%20Open&maxResults=0 liefert:

startAt 0
maxResults 0
total	3651
issues []

die gleiche Anfrage via WebRequest liefert: startAt: 0, maxResults: 0; total: 0, issues: [] 🙁

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myserver/rest/api/2/search?jql=status%20=%20Open&maxResults=0");
            
try
{        
request.Credentials =  new NetworkCredential(connection.username, connection.password);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
Console.WriteLine("Response stream received.");
Console.WriteLine(readStream.ReadToEnd());
response.Close();
readStream.Close();
}
catch (Exception e) { Console.WriteLine(e); }

Ich brauche den value "total" des Headers .. er bleibt immer 0