Table Design

Table Design

am 29.09.2005 13:45:58 von MrFreeze

Hallo

Mein PHP Script speichert zur Zeit alle Inforamtionen in einer ASCCI-File.
Das soll umgestellt werden auf mySQL.

In den Files befinden sich weit mehr über 30tausend Zeilen an
Informationen. Diese müssen in die Table geschrieben werden und es werden
von Tag zu Tag um tausend Einträge mehr!

Nun meine Frage - wie sollte ich das Design der Table gestallten um die
Belastung des Server niedrig und die Geschweindigkeit hoch zu halten?

Information die in der Ascii stehen Zeie für Zeile:
1125446162#100|
1125446157#100|
usw.

Eigendlich dachte ich an so etwas:

CREATE TABLE `result_table` (
`data` varchar(20) NOT NULL default '',
KEY `data` (`data`)
) ENGINE=MyISAM;

habt Ihr ne bessere Idee? oder gar andere Ideen?

Danke Euch für Eure Meinungen
HS

Re: Table Design

am 29.09.2005 13:58:14 von Krsten

Hans Schütt schrieb:
> Hallo
>
> Mein PHP Script speichert zur Zeit alle Inforamtionen in einer ASCCI-File.
> Das soll umgestellt werden auf mySQL.
>
> In den Files befinden sich weit mehr über 30tausend Zeilen an
> Informationen. Diese müssen in die Table geschrieben werden und es werden
> von Tag zu Tag um tausend Einträge mehr!
>
> Nun meine Frage - wie sollte ich das Design der Table gestallten um die
> Belastung des Server niedrig und die Geschweindigkeit hoch zu halten?
>
> Information die in der Ascii stehen Zeie für Zeile:
> 1125446162#100|
> 1125446157#100|
> usw.
>
> Eigendlich dachte ich an so etwas:
>
> CREATE TABLE `result_table` (
> `data` varchar(20) NOT NULL default '',
> KEY `data` (`data`)
> ) ENGINE=MyISAM;
>
> habt Ihr ne bessere Idee? oder gar andere Ideen?
>
> Danke Euch für Eure Meinungen
> HS
Wenn du sonst keine Daten hast die da rein sollen, ist das ok, allerding
ist die Frage ob die Werte nich tdoppelt vorkommen können, dann soltest
du lieber noc eine id als Schlüssel hinzufügen und einen index auf data
setzen.

-Kirsten

Re: Table Design

am 29.09.2005 14:00:00 von Ulf Wendel

Hans Schütt wrote:
> Information die in der Ascii stehen Zeie für Zeile:
> 1125446162#100|
> 1125446157#100|
> usw.
>
> Eigendlich dachte ich an so etwas:
>
> CREATE TABLE `result_table` (
> `data` varchar(20) NOT NULL default '',
> KEY `data` (`data`)
> ) ENGINE=MyISAM;
>
> habt Ihr ne bessere Idee? oder gar andere Ideen?

Es ist erfreulich, daß Du jetzt umsteigen willst. Hast Du irgendwelche
Erfahrungen mit Relationalen Datenbanken? Falls nicht, dann lese bitte
ein kleines Einführungstutorial, bevor Du beginnst. Noch besser wäre
natürlich ein Büchlein.

Dein Tabellendesign orientiert noch sehr stark am Flatfile Gedankengut.
Ich vermute, daß Deinen Datensätzen eine Semantik zugrunde liegt.
Analysiere die Semantik und verwende eine Spalte für jedes Datenfeld.

Wenn Du mit der folgenden Zeile meinst:

> 1125446157#100|

ID = 1125446157, Wert = 100 dann lege es als zwei Spalten in der DB ab.

CREATE TABLE result_table (
result_id UNSIGNED INTEGER NOT NULL,
value ???,
PRIMARY KEY (result_id)
)

Doch ohne die Semantik der Einträge zu verstehen wird Dir niemand einen
genauen Vorschlag machen können. Diesmal hast Du Wert = 100. Wert sieht
hier aus wie eine Ganzzahl (INTEGER), im letzten Posting sah es noch aus
wie ein FLOAT. Ob ID = 1125446157 eindeutig ist für alle deine
Datensätze kann man auch nur raten. Deshalb kann ich nur vermuten, daß
es als Schlüssel definiert werden sollte.

Dein Tabellenentwurf sieht so aus, als würdest Du einfach nur File gegen
Table tauschen. Das willst Du nicht. Du willst lernen was es mit der
Relationalen Datenspeicherung auf sich hat. Deshalb die Frage nach dem Buch.

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 29.09.2005 14:14:36 von MrFreeze

ok danke erstmal

Eine Frage hab ich aber noch!
Ich habe für jeden User eine solche Ascii-Datei mit sovielen Einträgen.

Nun habe ich überlegt ob die Ausgabe später der Daten schneller geht wenn
ich für jeden User eine eigene Table anlege.

oder soll ich alle user in eine Table speichern und mittels einer UserID
diese dann "filtern".

Ich bilde mir ein wenn jeder ne eigene Table bekommt würde es schneller
gehen!

denn eine Table weit über eine Million Einträge oder aber
Tausend Tables a 30tausen Einträge?


Wiviele Table maximal kann eien DB verwalten?

Re: Table Design

am 29.09.2005 14:43:44 von Ulf Wendel

Hans Schütt wrote:
> Nun habe ich überlegt ob die Ausgabe später der Daten schneller geht wenn
> ich für jeden User eine eigene Table anlege.
>
> oder soll ich alle user in eine Table speichern und mittels einer UserID
> diese dann "filtern".

Eine Tabelle, neue Spalte UserID UNSIGNED INTEGER.

> Ich bilde mir ein wenn jeder ne eigene Table bekommt würde es schneller
> gehen!

Nicht notwendigerweise. Eher sogar noch langsamer, weil sich eine
schlechtere Zwischenspeichernutzung ergeben könnte.

Hier eine exemplarische Rechnung ohne Anspruch auf exakte Werte. Es geht
nur um die Funktionsweise beim Lesen der Daten.

30.000 Einträge eine Mini-Tabelle mit einer UNSIGNED INTEGER und einer
kleinen FLOAT Spalte, werden oft zu einem Tablescan führen. Die zwei
Spalten UNSIGNED INTEGER und FLOAT belegen 8 Byte. MySQL-InnoDB
verwendet als Standard Datenseiten mit 16 kb. Es passen also sehr viele
Datensätze auf eine Datenseite. Eine Datenseite ist typischerweise die
kleinste I/O-Einheit einer Datenbank. Pro I/0-Zugriff wird MySQL sehr
grob gerechnet 16.000 / 8 = 2.000 Datensätze einlesen. I/O ist einer der
wesentlichen Kostenfaktoren für eine Datenbank.

Für eine Tabelle mit 30.000 Einträgen aus deiner Mini-Tabelle werden
also bummelig 15 Datenseiten benötigt. 15 Datenseiten bedeutet 15
I/O-Zugriffe. Das ist so wenig, daß InnoDB möglicherweise sogar auf
Indexzugriffe verzichtet und Tablescans bevorzugt.

Um I/O zu beschleunigen, legen Datenbanken die Datenseiten in schnellen
Zwischenspeichern, im Hauptspeicher (Cache) ab. Die Kapazität von
Zwischenspeichern ist begrenzt. Nehmen wir mal an da passen 100
Datenseiten rein. 100 Datenseiten genügen, um 6-7 der Mini-Tabellen mit
je 15 Datenseiten zu speichern.

Spätestens bei der 8. Mini-Tabelle beginnt die Verdrängung der
Datenseiten, die zur 1. Mini-Tabelle gehören. Darauffolgende Anfragen
an die Tabelle von User 1, Mini-Tabelle 1 können nicht mehr aus dem
Cache beantwortet werden. Mini-Tabelle 1 wurde durch Mini-Tabelle 8
verdrängt und muß neu von der Platte eingelesen werden, was teuer ist.

Es besteht die Gefahr, daß nur wenige Einträge im Zwischenspeicher
wiederverwendet werden können und viele Verdrängungen auftreten.

> denn eine Table weit über eine Million Einträge oder aber
> Tausend Tables a 30tausen Einträge?

Bei einigen Millionen Einträgen wird die Tabelle so groß, daß die
Datenbank einen Index-Scan verwenden wird. Von einem gecachten Index
profitieren alle User. Es ist wahrscheinlich, daß der Index komplett in
den Zwischenspeicher paßt. Wenn der Index komplett im Cache gehalten
werden kann, dann wird die Datenseite sehr schnell gefunden, die einen
bestimmten Datensatz enthält. Diese eine Datenseite im Bedarfsfall in
den Cache nachzuladen ist nicht so schlimm wie alle Datenseiten für
einen Tabelscan nachzuladen.

Erst bei der Frage des Lockings können - je nach Implementierung der DB
- mehrere Tabelle von Vorteil sein. Aber darüber würde ich mir bei
dieser offensichtlich noch kleinen Anwendung noch keine Gedanken machen.

Das einzige worauf Du achten mußt, falls Du mit MyISAM spielen solltest
ist MAX_ROWS, siehe http://dev.mysql.com/doc/mysql/en/create-table.html .

> Wiviele Table maximal kann eien DB verwalten?

Das ist herstellerabhängig. Für MySQL gibt es keine (relevante) Limitierung.

Was in der Praxis vorkommt ist schwer zu sagen. Vielleicht kann man SAP
Anwendungen als ein Beispiel nehmen. Hier gibt es bereits in den
Standardinstallationen zehntausende von Tabellen und zehntausende von Views.

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 11:12:57 von MrFreeze

Moin NG,


Ich ahbe die ganze nacht nun drann gesessen und die tausenden Einträge in
die DB importiert!
Insgesammt befinden sich derzeit 5871248 Datensätze nun in der DB.
Jeden Tag würden ca 80000 dazu kommen.


Eine Abfrage dauert bis zur Ausgabe des Ergebnisses 6 Sek.
Das ist nicht schön.

Also werd ich wohl auf ASCII bleiben - da dauert es nur 2 sek.
Oder hat jemand eine Ideee

Re: Table Design

am 30.09.2005 11:34:07 von Ulf Wendel

Hans Schütt wrote:
> Insgesammt befinden sich derzeit 5871248 Datensätze nun in der DB.
> Jeden Tag würden ca 80000 dazu kommen.
>
>
> Eine Abfrage dauert bis zur Ausgabe des Ergebnisses 6 Sek.
> Das ist nicht schön.

Liefere bitte folgende Infos:

SHOW VARIABLES
SHOW CREATE TABLE meinetabelle
SHOW INDEXES FROM meinetabelle
EXPLAIN meine_langsame_sql_anfrage

Ohne diese Angaben kann niemand eine MySQL Query tunen.

Benutzt Du kalte Caches oder sind diese schon heiß? Kalt sind sie, wenn
Du zum ersten mal eine Query ausführst und die Datenbank noch alle Daten
von der Platte laden muß. Von einem heißen Cache, einem eingeschwungenen
System, spricht man, wenn die Daten bereits im Cache vorliegen und die
Datenbank deshalb keine teuren Plattenzugriffe mehr ausführen muß.

Aber langsam verläßt deine Frage die PHP-Welt. Vielleicht willst Du auf
eine andere Newsgroup wechseln.

Ulf


--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 12:11:51 von MrFreeze

> EXPLAIN meine_langsame_sql_anfrage
$sql = @mysql_query("SELECT i_time, i_request, i_content, i_service_id FROM ". RESULT_TABLE." WHERE i_service_id='$get_id'");
$sql_count = @mysql_num_rows($sql);

Erklären muss "alle" Datensätzte verarbeinte die i_service_id = $get_id sind


> SHOW CREATE TABLE meinetabelle

monitor_result_table | CREATE TABLE `monitor_result_table` (
`i_time` int(11) NOT NULL default '0',
`i_request` varchar(8) NOT NULL default '0.00',
`i_content` int(120) unsigned NOT NULL default '0',
`i_service_id` int(120) unsigned NOT NULL default '0',
KEY `i_time` (`i_time`)
) TYPE=MyISAM



> SHOW INDEXES FROM meinetabelle

+----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Comment |
+----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+
| monitor_result_table | 1 | i_time | 1 | i_time | A | NULL | NULL | NULL | |
+----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+







> SHOW VARIABLES

+---------------------------------+------------------------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------+
| Variable_name | Value |
+---------------------------------+------------------------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------+
| back_log | 50 |
| basedir | /usr/local/mysql-3.23.57-pc-linux-i686/ |
| binlog_cache_size | 32768 |
| character_set | latin1 |
| character_sets | latin1 big5 czech euc_kr gb2312 gbk sjis tis620 ujis dec8 dos german1 hp8 koi8_ru latin2 swe7 usa7 cp1251 danish hebrew win1251 estonia hungarian koi8_ukr win1251ukr greek win1250 croat cp1257 latin5 |
| concurrent_insert | ON |
| connect_timeout | 5 |
| datadir | /home/database/ |
| delay_key_write | ON |
| delayed_insert_limit | 100 |
| delayed_insert_timeout | 300 |
| delayed_queue_size | 1000 |
| flush | OFF |
| flush_time | 0 |
| have_bdb | NO |
| have_gemini | NO |
| have_innodb | NO |
| have_isam | YES |
| have_raid | NO |
| have_openssl | NO |
| init_file | |
| interactive_timeout | 28800 |
| join_buffer_size | 131072 |
| key_buffer_size | 16773120 |
| language | /usr/local/mysql-3.23.57-pc-linux-i686/share/mysql/english/ |
| large_files_support | ON |
| locked_in_memory | OFF |
| log | OFF |
| log_update | OFF |
| log_bin | OFF |
| log_slave_updates | OFF |
| log_long_queries | OFF |
| long_query_time | 10 |
| low_priority_updates | OFF |
| lower_case_table_names | 0 |
| max_allowed_packet | 16776192 |
| max_binlog_cache_size | 4294967295 |
| max_binlog_size | 1073741824 |
| max_connections | 2200 |
| max_connect_errors | 10 |
| max_delayed_threads | 20 |
| max_heap_table_size | 16777216 |
| max_join_size | 4294967295 |
| max_sort_length | 1024 |
| max_user_connections | 0 |
| max_tmp_tables | 32 |
| max_write_lock_count | 4294967295 |
| myisam_max_extra_sort_file_size | 256 |
| myisam_max_sort_file_size | 2047 |
| myisam_recover_options | 0 |
| myisam_sort_buffer_size | 8388608 |
| net_buffer_length | 7168 |
| net_read_timeout | 30 |
| net_retry_count | 10 |
| net_write_timeout | 60 |
| open_files_limit | 0 |
| pid_file | /home/database/www9.c.artfiles.de.pid |
| port | 3306 |
| protocol_version | 10 |
| record_buffer | 131072 |
| record_rnd_buffer | 131072 |
| query_buffer_size | 0 |
| safe_show_database | OFF |
| server_id | 1 |
| slave_net_timeout | 3600 |
| skip_locking | ON |
| skip_networking | OFF |
| skip_show_database | OFF |
| slow_launch_time | 2 |
| socket | /tmp/mysql.sock |
| sort_buffer | 524280 |
| sql_mode | 0 |
| table_cache | 1024 |
| table_type | MYISAM |
| thread_cache_size | 0 |
| thread_stack | 129024 |
| transaction_isolation | READ-COMMITTED |
| timezone | CEST |
| tmp_table_size | 100000 |
| tmpdir | /tmp/ |
| version | 3.23.57 |
| wait_timeout | 900 |
+---------------------------------+------------------------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------+

Re: Table Design

am 30.09.2005 12:24:49 von Ulf Wendel

Hans Schütt wrote:
>>EXPLAIN meine_langsame_sql_anfrage
>
> $sql = @mysql_query("SELECT i_time, i_request, i_content, i_service_id FROM ". RESULT_TABLE." WHERE i_service_id='$get_id'");
> $sql_count = @mysql_num_rows($sql);

Bitte führe folgendes im MySQL Prompt aus und poste die Ausgabe:

EXPLAIN SELECT i_time, i_request, i_content, i_service_id FROM
monitor_result_table WHERE i_service_id = [irgendeine gültige ID]

EXPLAIN ist _das_ Mittel herauszufinden warum eine Query langsam ist,
siehe: "http://dev.mysql.com/doc/mysql/en/numeric-types.html

> Erklären muss "alle" Datensätzte verarbeinte die i_service_id = $get_id sind
>
>
>
>>SHOW CREATE TABLE meinetabelle
>
>
> monitor_result_table | CREATE TABLE `monitor_result_table` (
> `i_time` int(11) NOT NULL default '0',
> `i_request` varchar(8) NOT NULL default '0.00',
> `i_content` int(120) unsigned NOT NULL default '0',
> `i_service_id` int(120) unsigned NOT NULL default '0',

int(120) macht keinen Sinn. (120) ist hier ein Formatierungshinweis
nicht mehr. Siehe auch:
http://dev.mysql.com/doc/mysql/en/numeric-types.html .

> KEY `i_time` (`i_time`)
> ) TYPE=MyISAM
>
>
>
>
>>SHOW INDEXES FROM meinetabelle
>
>
> +----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+
> | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Comment |
> +----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+
> | monitor_result_table | 1 | i_time | 1 | i_time | A | NULL | NULL | NULL | |
> +----------------------+------------+----------+------------ --+-------------+-----------+-------------+----------+------ --+---------+

Auf der Spalte i_service_id ist kein Index definiert. Die Datenbank muß
die gesamte Tabelle durchsuchen, es gibt einen Tablescan. Das kann nicht
schnell sein.

Als Sofortmaßnahme mach mal:

CREATE INDEX idx_i_server_id (i_service_id) ON monitor_result_table

Danach erkläre mal welche Bedeutungen die Spalten in deiner Tabelle haben.

>>SHOW VARIABLES
>
>
> +---------------------------------+------------------------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------+
> | Variable_name | Value |
> +---------------------------------+------------------------- ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------+
> | back_log | 50 |
> | basedir | /usr/local/mysql-3.23.57-pc-linux-i686/ |

[...]

> | version | 3.23.57 |

Brr, muß das sein? 3.23 ist schon ein paar Tage alt und enthält nicht
alle Optimierungen, die neue Versionen mit sich bringen.

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 12:26:46 von Ulf Wendel

Ulf Wendel wrote:
> Hans Schütt wrote:
> CREATE INDEX idx_i_server_id (i_service_id) ON monitor_result_table

Uuups - Dreher.

CREATE INDEX idx_i_server_id ON monitor_result_table (i_service_id)

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 12:32:36 von Fabian Schladitz

Hans Schütt schrieb:
>> EXPLAIN meine_langsame_sql_anfrage
>=20
> $sql =3D @mysql_query("SELECT i_time, i_request, i_content,=20
> i_service_id FROM ". RESULT_TABLE." WHERE i_service_id=3D'$get_id'");=20
> $sql_count =3D @mysql_num_rows($sql);
>=20
> Erklären muss "alle" Datensätzte verarbeinte die i_service_id =3D =

> $get_id sind

Also:

Warum '$get_id'? Da sollte nur $get_id sein, da i_service_id als INTEGER
definiert ist. Übergib MySQL also keinen String. Da muss unnötig
umgewandelt werden.

>> SHOW CREATE TABLE meinetabelle
>=20
>=20
> monitor_result_table | CREATE TABLE `monitor_result_table` ( `i_time`
> int(11) NOT NULL default '0', `i_request` varchar(8) NOT NULL
> default '0.00', `i_content` int(120) unsigned NOT NULL default '0',

Die 120 ist da doch eher witzlos. Es handelt sich um die DISPLAY Breite.
Also nur die Anzeige. Welche Werte erwartest du dort als Maximum?

> `i_service_id` int(120) unsigned NOT NULL default '0',
> KEY `i_time` (`i_time`) ) TYPE=3DMyISAM

Warum hast du keinen Index auf die Spalte gelegt, die du in der=20
WHERE-Klausel verwendest? Dadurch muss deine Abfrage _immer_ einen Full=20
Table Scan machen. Das ist sehr ungünstig.

>> SHOW INDEXES FROM meinetabelle

Wie gesagt: setze noch einen auf i_service_id.

Dann sinken deine Abfragezeiten deutlich.

--=20
HTH,
Fabian

Re: Table Design

am 30.09.2005 12:56:12 von MrFreeze

Ulf Wendel wrote in news:dhj3u3$nbj$04$2@news.t-
online.com:

> Ulf Wendel wrote:
>> Hans Schütt wrote:
>> CREATE INDEX idx_i_server_id (i_service_id) ON monitor_result_table
>
> Uuups - Dreher.
>
> CREATE INDEX idx_i_server_id ON monitor_result_table (i_service_id)
>
> Ulf
>

Hi Ulf!

Ok habe nun diesen IDEX auch!
Und jo - o wie schön von 6 sekunden runter auf 0.5 -> 1.5 Sekunden!
Bin hin und weg - gibt es noch mehr optimierungsmöglichkeiten?!
Den es werden ja sehr schnell 10Million einträge werden und ein ende ist
nicht in sicht!
Und habe bissel Angst das es dann langsammer wird.

Was würdest Du persönlich bei solchen Datenmengen machen?!


Ich habe bis jetzt sehr zu Danken!
HS

Re: Table Design

am 30.09.2005 13:09:46 von Fabian Schladitz

Hans Schütt schrieb:
> Ulf Wendel wrote in news:dhj3u3$nbj$04$2@news.t-=

> online.com:

^^^^^^^^ mach da mal eine Zeile daraus...

>=20
>>Ulf Wendel wrote:
>>
>>>Hans Schütt wrote:
>>>CREATE INDEX idx_i_server_id (i_service_id) ON monitor_result_table
>>
>>Uuups - Dreher.
>>
>>CREATE INDEX idx_i_server_id ON monitor_result_table (i_service_id)
>>
>>Ulf
>>
>=20
> Hi Ulf!

Ich mische mich einfach mal ein...

>=20
> Ok habe nun diesen IDEX auch!
> Und jo - o wie schön von 6 sekunden runter auf 0.5 -> 1.5 Sekunden!
> Bin hin und weg - gibt es noch mehr optimierungsmöglichkeiten?!

Jede Menge. Lies doch mal im MySQL Manual nach - dort ist schon sehr=20
viel abgedeckt.

> Den es werden ja sehr schnell 10Million einträge werden und ein ende =
ist=20
> nicht in sicht!
> Und habe bissel Angst das es dann langsammer wird.

Das kommt ganz auf die Beschaffenheit der Daten und die Art der Abfragen =

an. Wenn du uns noch erhellen kannst, was deine Daten darstellen und=20
warum du die Spaltentypen so gesetzt hast, wie du es tust, können wir=20
vielleicht weiterhelfen.
Bei den Abfragen kommt es vor Allem auf Indexe an. Aber setz keine=20
unnötigen.

> Was würdest Du persönlich bei solchen Datenmengen machen?!

Meinen MySQL-Server richtig einstellen und ausstatten, das Datenmodell=20
überprüfen, Backup/Replikation einrichten, falls die Daten wichtig si=
nd=20
und dann zurücklehnen und was anderes tun.

--=20
HTH,
Fabian

Re: Table Design

am 30.09.2005 13:13:40 von Ulf Wendel

Hans Schütt wrote:
> Ok habe nun diesen IDEX auch!
> Und jo - o wie schön von 6 sekunden runter auf 0.5 -> 1.5 Sekunden!
> Bin hin und weg - gibt es noch mehr optimierungsmöglichkeiten?!

Moin Hans,

es gibt oft noch ein paar Optionen, aber da fängst Du an Kompromisse zu
machen. Z.B. kann man mit komprimierten MyISAM-Tabellen spielen. Hier
ist der Speicherbedarf geringer und damit wird weniger von der Platte
geladen (was Zeit kostet), mehr paßt in den Cache etc. Aber hier fangen
die Kompromisse an: komprimierte MyISAM-Tabellen sind read-only.

Wenn eine halbe Sekunde OK ist, dann laß es dabei. Mit Hausmitteln ist
hier Schluß. Führe mal die Query zwei mal nacheinander mit
unterschiedlichen ID's aus, vielleicht sind 0.5 Sekunden ja auch nicht
der Wert für kalte Caches.

Du kannst mal schauen ob in einem aktuellen MySQL InnoDB und/oder
Archive schneller sind. InnoDB skaliert sehr gut, hat inzwischen auch
eine kompakte Storage und könnte noch stärker von sequentiellen
Plattenzugriffen innerhalb eines InnoDB Extends profitieren.

> Den es werden ja sehr schnell 10Million einträge werden und ein ende ist
> nicht in sicht!
> Und habe bissel Angst das es dann langsammer wird.

MyISAM verwendet B-Bäume für Indizes. Die Suchtiefe in einem B-Baum
wächst nicht dramatisch an, wenn deine Tabelle größer wird. Die Tiefe
wächst bei weitem nicht linear. Jetzt macht die DB vielleicht 7 oder 8
Suchoperationen im B-Baum. Vielleicht kommt bei 10 Millionen Einträgen
eine Ebene im Baum, also eine Suchoperation hinzu. Das macht den Kohl
nicht fett.

Übel wird es immer dann, wenn man nicht mehr aus einem Cache arbeitet
sondern von der Platte liest oder wenn es Probleme gibt einen
effizienten Ausführungsplan zu finden.

> Was würdest Du persönlich bei solchen Datenmengen machen?!

Nichts. Das sind noch keine kritischen Datenmengen und die Query ist
"langweilig".

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 13:13:41 von MrFreeze

>> monitor_result_table | CREATE TABLE `monitor_result_table` ( `i_time`
>> int(11) NOT NULL default '0', `i_request` varchar(8) NOT NULL
>> default '0.00', `i_content` int(120) unsigned NOT NULL default '0',
>
> Die 120 ist da doch eher witzlos. Es handelt sich um die DISPLAY Breite.
> Also nur die Anzeige. Welche Werte erwartest du dort als Maximum?
HI ich ahbe aus int(120) ein mediumint(8) gemacht


>> `i_service_id` int(120) unsigned NOT NULL default '0',
>> KEY `i_time` (`i_time`) ) TYPE=MyISAM
>
> Warum hast du keinen Index auf die Spalte gelegt, die du in der
> WHERE-Klausel verwendest? Dadurch muss deine Abfrage _immer_ einen Full
> Table Scan machen. Das ist sehr ungünstig.
Jo habe ich gemacht - das hat allse verbessert!
Danke

Re: Table Design

am 30.09.2005 13:45:36 von MrFreeze

Fabian Schladitz wrote in news:dhj6l3$ibt$1@news.web.de:



> Das kommt ganz auf die Beschaffenheit der Daten und die Art der Abfragen
> an. Wenn du uns noch erhellen kannst, was deine Daten darstellen und
> warum du die Spaltentypen so gesetzt hast, wie du es tust, können wir
> vielleicht weiterhelfen.
> Bei den Abfragen kommt es vor Allem auf Indexe an. Aber setz keine
> unnötigen.

Also die Daten sehe wie folgt aus:


i_time, i_request, i_content, i_service_id

VALUES (1124310062, '100', 0, 7);
VALUES (1124310062, '100', 0, 7);
VALUES (1124310062, '100', 0, 7);
VALUES (1124310063, '100', 0, 7);
VALUES (1124310063, '100', 0, 7);
VALUES (1124310063, '0.0130', 0, 8);
VALUES (1124310063, '0.0134', 0, 8);


i_time => Timestamp wann der Eintrag gemacht wurde
i_request => Wie Lange hat der Vorgang gebraucht entweder Sekunde angabe oder 100 für Fehlerhaft
i_content => Ein integer ob es weiter Informationen gab - Möglichkeiten 1 oder 2
i_service_id => Eine ID über die ich das jeweilige Modul identifiziere die diese Einträge erstellte

Re: Table Design

am 30.09.2005 14:02:04 von MrFreeze

Ulf Wendel wrote in
news:dhj3qf$nbj$04$1@news.t-online.com:


> Bitte führe folgendes im MySQL Prompt aus und poste die Ausgabe:
>
> EXPLAIN SELECT i_time, i_request, i_content, i_service_id FROM
> monitor_result_table WHERE i_service_id = [irgendeine gültige ID]
>
> EXPLAIN ist _das_ Mittel herauszufinden warum eine Query langsam ist,
> siehe: "http://dev.mysql.com/doc/mysql/en/numeric-types.html

hmmm dem Result zu urteilen ist alles schnell!
+----------------------+------+-----------------+----------- ------+---------+-------+-------+------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+----------------------+------+-----------------+----------- ------+---------+-------+-------+------------+
| monitor_result_table | ref | idx_i_server_id | idx_i_server_id | 3 | const | 54056 | where used |
+----------------------+------+-----------------+----------- ------+---------+-------+-------+------------+
1 row in set (0.00 sec)

Allerdings dauert die gleich ausgabe in PHP/Browser 2,516 sek durschnittlich


> int(120) macht keinen Sinn. (120) ist hier ein Formatierungshinweis
> nicht mehr. Siehe auch:
> http://dev.mysql.com/doc/mysql/en/numeric-types.html .
geändert in mediumint(8)


> Auf der Spalte i_service_id ist kein Index definiert. Die Datenbank
> muß die gesamte Tabelle durchsuchen, es gibt einen Tablescan. Das kann
> nicht schnell sein.
>
> Als Sofortmaßnahme mach mal:
>
> CREATE INDEX idx_i_server_id (i_service_id) ON monitor_result_table
>
> Danach erkläre mal welche Bedeutungen die Spalten in deiner Tabelle
> haben.
Hab ich gemacht in einem anderen post gerade ;)


> Brr, muß das sein? 3.23 ist schon ein paar Tage alt und enthält nicht
> alle Optimierungen, die neue Versionen mit sich bringen.

Hmm meinst Du das es Spürbare geschwindigkeitsvorteile gäbe bei einer 4.1?

Re: Table Design

am 30.09.2005 14:13:30 von Ulf Wendel

Hans Schütt wrote:
> Fabian Schladitz wrote in news:dhj6l3$ibt$1@news.web.de:
>
>
>
>
>>Das kommt ganz auf die Beschaffenheit der Daten und die Art der Abfragen
>>an. Wenn du uns noch erhellen kannst, was deine Daten darstellen und
>>warum du die Spaltentypen so gesetzt hast, wie du es tust, können wir
>>vielleicht weiterhelfen.
>>Bei den Abfragen kommt es vor Allem auf Indexe an. Aber setz keine
>>unnötigen.
>
>
> Also die Daten sehe wie folgt aus:
>
>
> i_time, i_request, i_content, i_service_id
>
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310063, '100', 0, 7);
> VALUES (1124310063, '100', 0, 7);
> VALUES (1124310063, '0.0130', 0, 8);
> VALUES (1124310063, '0.0134', 0, 8);
>
>
> i_time => Timestamp wann der Eintrag gemacht wurde
> i_request => Wie Lange hat der Vorgang gebraucht entweder Sekunde angabe oder 100 für Fehlerhaft
> i_content => Ein integer ob es weiter Informationen gab - Möglichkeiten 1 oder 2
> i_service_id => Eine ID über die ich das jeweilige Modul identifiziere die diese Einträge erstellte

Deine Wahl an Spaltentypen ist unglücklich. Verwende immer einen
Spaltentyp, der den Inhalt representiert, sofern der Typ kompatibel ist
mit deinen Werteumfang. Wähle den platzsparsamsten Typ der für eine
Spalte in Frage kommt, um den Speicherbedarf der Tabelle zu drücken.
Viel Platzbedarf bedeutet viele Leseoperationen, Leseoperationen sind
teuer, ...

Aktuell scheinst Du zu benutzen:

monitor_result_table | CREATE TABLE `monitor_result_table` (
`i_time` int(11) NOT NULL default '0',
`i_request` varchar(8) NOT NULL default '0.00',
`i_content` int(120) unsigned NOT NULL default '0',
`i_service_id` int(120) unsigned NOT NULL default '0',
KEY `i_time` (`i_time`)
) TYPE=MyISAM


Denk mal über folgende Alternative nach:

i_time TIMESTAMP NOT NULL,
i_request FLOAT NOT NULL DEFAULT 0.0,
i_content ENUM(1, 2) NOT NULL,
i_service_id MEDIUMINT UNSIGNED NOT NULL

Die Kodierung von i_request = 100 => Fehler ist nicht unbedingt guter
Stil. Niemand kann ohne gute Dokumentation feststellen, ob i_request =
100 ein gültiger Wert ist oder eine besondere semantische Bedeutung hat.

Um etwas über benötigte Indizes zu sagen, muß man die Anfragen kennen,
die an die Tabelle gestellt werden. Das Fehlen eines Primärschlüssels,
eines eindeutigen Identifiers für einen Datensatz, ist zwar denkbar aber
nicht immer erwünscht. Je nach Applikationslogik könnte auch hier
nachgebessert werden.

Ulf

--
Internet Super Hero - It's all about Nixnutz
http://www.internetsuperhero.de

Re: Table Design

am 30.09.2005 14:18:33 von Fabian Schladitz

Hans Schütt schrieb:
> Fabian Schladitz wrote in news:dhj6l3$ibt$1@news.web=
de:
>=20
>>Das kommt ganz auf die Beschaffenheit der Daten und die Art der Abfrage=
n=20
>>an. Wenn du uns noch erhellen kannst, was deine Daten darstellen und=20
>>warum du die Spaltentypen so gesetzt hast, wie du es tust, können wir=
=20
>>vielleicht weiterhelfen.
>>Bei den Abfragen kommt es vor Allem auf Indexe an. Aber setz keine=20
>>unnötigen.
>=20
> Also die Daten sehe wie folgt aus:
>=20
> i_time, i_request, i_content, i_service_id=20
>=20
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310062, '100', 0, 7);
> VALUES (1124310063, '100', 0, 7);
> VALUES (1124310063, '100', 0, 7);
> VALUES (1124310063, '0.0130', 0, 8);
> VALUES (1124310063, '0.0134', 0, 8);
>=20
>=20
> i_time =3D> Timestamp wann der Eintrag gemacht wurde
> i_request =3D> Wie Lange hat der Vorgang gebraucht entweder Sekunde =
angabe oder 100 für Fehlerhaft
> i_content =3D> Ein integer ob es weiter Informationen gab - Möglic=
hkeiten 1 oder 2
> i_service_id =3D> Eine ID über die ich das jeweilige Modul identifizi=
ere die diese Einträge erstellte

Kannst du den Input verändern? Also z.B. sollte das "100 für Fehlerha=
ft"=20
weg. Da bietet sich ein NULL an. Dann ist die Definition sauberer und=20
man benötigt weniger Hintergrundwissen.
Was passiert mit dein weiteren Informationen? Hälst du die auch irgendw=
o=20
vor?

Ich würde an deiner Stelle auf den Timestamp verzichten und ein=20
"richtiges" DATETIME nehmen. Dafür gibt es dann schicke Funktionen im=20
SQL-Query.

Was aber viel interessanter ist und du noch nicht beantwortet hast:=20
welche Abfragen laufen gegen die Daten? Welche Fragestellungen habt ihr?
Dann könnte man sehen, wo andere Indexe nötig sind oder was man sonst=
=20
verbesser kann.

Im Moment hast du ja nur eine Datensenke und noch keine relationale=20
Datenbank.

--=20
HTH,
Fabian

Re: Table Design

am 14.10.2005 10:37:56 von Ingo Hamann

Hans Schütt schrieb:
> Hallo
>
> Mein PHP Script speichert zur Zeit alle Inforamtionen in einer ASCCI-File.
> Das soll umgestellt werden auf mySQL.
>
> In den Files befinden sich weit mehr über 30tausend Zeilen an
> Informationen. Diese müssen in die Table geschrieben werden und es werden
> von Tag zu Tag um tausend Einträge mehr!
>
> Nun meine Frage - wie sollte ich das Design der Table gestallten um die
> Belastung des Server niedrig und die Geschweindigkeit hoch zu halten?
>
> Information die in der Ascii stehen Zeie für Zeile:
> 1125446162#100|
> 1125446157#100|
> usw.
>
> Eigendlich dachte ich an so etwas:
>
> CREATE TABLE `result_table` (
> `data` varchar(20) NOT NULL default '',
> KEY `data` (`data`)
> ) ENGINE=MyISAM;
>
> habt Ihr ne bessere Idee? oder gar andere Ideen?
>
> Danke Euch für Eure Meinungen
> HS

Hallo Hans,
bist Du sicher, dass Du all die Daten tatsächlich brauchst (zum Beispiel
um uralte Zugriffe auf ewige Zeit detailliert nachzuweisen)? Wenn nicht,
könnte man die Daten vom Server periodisch archivieren oder kumulieren
lassen oder auflaufende Daten sofort kumulieren. Dann reduziert sich das
GANZE Problem erheblich...
Gruß Ingo