MySQL und Tabelle > 500.000 Einträge

MySQL, PostgreSQL, SQLite
grafzahl
Posts: 19
Joined: 2002-09-11 19:39

MySQL und Tabelle > 500.000 Einträge

Post by grafzahl » 2004-06-07 09:03

Hallo zusammen,

ich habe eine Preissuchmaschine in Perl programmiert, welche anfangs auch super läuft. Nun habe ich ein Problem mit der Masse:

Ich erwarte etwa 5.000.000 Einträge in der MySQL Tablelle. Leider mußte ich feststellen, daß nach ca. 400.000 - 500.000 Einträge der MySQL Server bei einer Suchanfrage schon schlapp macht. Zeit bis Ergebiss: min. 10 Sekunden, Prozessorlast 99.7%.

Sobald es über 500.000 Einträge geht, hängt sich das System auf, so das ich nichtmal mehr mit Putty drauf komme. Confixx_Counterscript will nicht mehr, etc. Mit anderen Worten: 2 gleichzeitige Suchanfragen erfordern einen Reset, da nichts mehr geht.

Ich benutze einen Rootie L von 1&1 mit 2000er Celeron und 256 MB, der nun schon 1 Jahr einwandfrei läuft. Die MySQL Tabelle ist nach folgendem Schema aufgebaut:

Artikeltitel(Index) als VARCHAR(50)
URL als VARCHAR(100)
BildURL als VARCHAR(100)
Preis als DECIMAL(11,2)
Anbieter als INT(3)
Time als INT(11)

Meine my.cnf vom 3.23.57:

Code: Select all

[mysqld]
port            = 3306
socket          = /var/lib/mysql/mysql.sock
skip-locking
set-variable    = key_buffer=32M
set-variable    = max_allowed_packet=1M
set-variable    = table_cache=128
set-variable    = sort_buffer=4M
set-variable    = net_buffer_length=16K
set-variable    = myisam_sort_buffer_size=32M
set-variable    = wait_timeout=120
set-variable    = interactive_timeout=120
server-id        = 1
Die my.cnf ist meiner Meinung nach schon ganz okay oder ist jemand anderer Meinung ?

Derzeit muß ich den Artikelbestand unter 300.000 laufen lassen um eine vernünftige Performance zu gewährleisten.

Ich habe jetzt auch schon mehrere Stunden die MySQL Dokumentation durchforstet um eine Lösung zu finden, aber leider ohne Ergebniss.

Hat jemand einen Tipp zur Lösung meines Problems ?

Gruß Axel

metrax
Posts: 194
Joined: 2003-02-22 22:51
Location: München / Berg-am-Laim

Re: MySQL und Tabelle > 500.000 Einträge

Post by metrax » 2004-06-07 09:38

MySQL ist nicht für solche Massen ausgelegt. Versuchs mal mit PostgreSQL.

Wenn du weiterhin auf MySQL bestehst kann ich dir nur foldendes Raten:
- bedeutend stärkere CPU
- viel mehr RAM
- setz die priorität von mysql/perl runter um wieder per ssh auf den server zukommen.


Ich hab nen AMD Athlon 2200+ mit 1024 MB RAM. bis zu 2 Mio einträge in eine Tabelle schafft der locker, danach wirds kritisch.

MfG
Robert

oxygen
Posts: 2138
Joined: 2002-12-15 00:10
Location: Bergheim

Re: MySQL und Tabelle > 500.000 Einträge

Post by oxygen » 2004-06-07 10:03

Indexe bzw. Keys benutzten.
Auf MySQL 4 umstellen.

arty
Userprojekt
Userprojekt
Posts: 729
Joined: 2002-06-12 10:11

Re: MySQL und Tabelle > 500.000 Einträge

Post by arty » 2004-06-07 11:08

Wie durchsuchst du denn die DB?

bye
arty

Anonymous

Re: MySQL und Tabelle > 500.000 Einträge

Post by Anonymous » 2004-06-07 12:14

Bei einer Volltext-Suche ist das normal, da wird fast jede DB in die Knie gehen. Bei einer Suche über Indexe dürfte das nicht so lange dauern, daher meine Frage wie wird gesucht und wie genau ist die zu durchsuchende Tabelle definiert?



Sebo

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-07 13:50

500.000 Einträge sind für mysql ein Witz. Selbst 5 mio Einträge schafft mysql ohne große Probleme.

Wichtig ist allerdings (wie bei jeder anderen DB auch), dass du unbedingt die richtigen Indeces setzt, und möglichst auch nach diesen abfragst.

Außerdem gibt es ein Bug, der bei mysql 3 existiert, und Tabellen mit vielen Einträgen teilweise sehr langsam macht (trotz index). Abhilfe verschafft hier mysql 4.0.0+.

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-07 14:27

Primary Index über ein varchar[50] ???

Viel Spass, das kann nicht funktionieren.


Gruss,

Out

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-07 14:42

Wieso? mySQL benutzt auch bei varchar Indeces. Wieso soll das nicht funktionieren?

Natürlich ist es nicht die "feine Art", einen varchar als Primary Key zu benutzen, und es ist vielleicht auch minimal langsamer, es sollte aber trotzalledem funktionieren...

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-07 15:12

@kase:

Ganz einfach:

Ein Index über ein varchar ist technisch etwas ganz anderes als ein Key über einen Int z.B.
und wird intern vom Optimizer ganz anders gehandhabt, davon abgesehen dass du über sowas
mit like gehst anstatt mit "=", und dir das ganz andere Fehlerquellen verschaffen kann... (Stichwort "NULL")

Wie immer: Ohne eine genaue Tabellenstruktur und die Querries die darüber gehen wird das ein Glaskugelsuchen.... ich tippe mal auf ein "like '%irgendwas%'... und was der Optimizer damit macht, will keiner wirklich wissen. ;)

mysqladmin proc, ver, var und wir wissen mehr. ;)

Gruss,

Out

grafzahl
Posts: 19
Joined: 2002-09-11 19:39

Re: MySQL und Tabelle > 500.000 Einträge

Post by grafzahl » 2004-06-07 15:56

So, da bin ich wieder...

Es soll primär nach dem Titel gesucht werden mit einer Sortierung nach dem Preis. Ich habe um übrigen keinen PRIMARY KEY in dieser Tabelle, lediglich einen INDEX auf Artikeltitel.

Erstmal meine mysqladmin proc:

Code: Select all

+------+------+-----------+----+---------+------+-------+------------------+
| Id   | User | Host      | db | Command | Time | State | Info             |
+------+------+-----------+----+---------+------+-------+------------------+
| 5910 | root | localhost |    | Query   | 0    |       | show processlist |
+------+------+-----------+----+---------+------+-------+------------------+
mysqladmin ver

Code: Select all

mysqladmin  Ver 8.23 Distrib 3.23.57, for pc-linux on i686
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license

Server version          3.23.57
Protocol version        10
Connection              Localhost via UNIX socket
UNIX socket             /var/lib/mysql/mysql.sock
Uptime:                 16 hours 54 min 22 sec

Threads: 1  Questions: 315100  Slow queries: 2  Opens: 2226  Flush tables: 1  Open tables: 100 Queries per second avg: 5.177
und die große mysql proc (Ich hoffe es ist leserlich)

Code: Select all

back_log = 50                                                                                                                                                                                                      |
basedir 
/                                                                                                          

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                         | /var/lib/mysql/                                                                                                                                                                                         |
| 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             | 120                                                                                                                                                                                                     |
| join_buffer_size                | 131072                                                                                                                                                                                                  |
| key_buffer_size                 | 33550336                                                                                                                                                                                                |
| language                        | /usr/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              | 1047552                                                                                                                                                                                                 |
| max_binlog_cache_size           | 4294967295                                                                                                                                                                                              |
| max_binlog_size                 | 1073741824                                                                                                                                                                                              |
| max_connections                 | 100                                                                                                                                                                                                     |
| 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         | 33554432                                                                                                                                                                                                |
| net_buffer_length               | 15360                                                                                                                                                                                                   |
| net_read_timeout                | 30                                                                                                                                                                                                      |
| net_retry_count                 | 10                                                                                                                                                                                                      |
| net_write_timeout               | 60                                                                                                                                                                                                      |
| open_files_limit                | 0                                                                                                                                                                                                       |
| pid_file                        | /var/lib/mysql/mysqld.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                          | /var/lib/mysql/mysql.sock                                                                                                                                                                               |
| sort_buffer                     | 4194296                                                                                                                                                                                                 |
| sql_mode                        | 0                                                                                                                                                                                                       |
| table_cache                     | 128                                                                                                                                                                                                     |
| table_type                      | MYISAM                                                                                                                                                                                                  |
| thread_cache_size               | 0                                                                                                                                                                                                       |
| thread_stack                    | 65536                                                                                                                                                                                                   |
| transaction_isolation           | READ-COMMITTED                                                                                                                                                                                          |
| timezone                        | CEST                                                                                                                                                                                                    |
| tmp_table_size                  | 33554432                                                                                                                                                                                                |
| tmpdir                          | /tmp/                                                                                                                                                                                                   |
| version                         | 3.23.57                                                                                                                                                                                                 |
| wait_timeout                    | 120

Ich denke mal das wäre genug Lesestoff :-)
Danke für die rege Anteilnahme.

Gruß Axel

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-07 16:06

Allao gut, also 18,5k Querries pro Stunde.

Leider sieht man nicht, was für Querries das sind. (Deshalb hab ich nach dem mysqladmin proc gefragt). Ist da die DB grad unten gewesen?

Hast du die Logs angeschaltet? Kommen dort Querries vor die sich oft wiederholen?

Wie viele Querries machst du pro Seitenzugriff auf diese Tabelle?

Was für eine Abfrage machst du genau über diese Tabelle?

Du sagtest Preisvergleich... also gibt es Titel die identisch sind, und du suchst
alle mit dem gleichen Namen?
Dann würde ich eine zweite Tabelle machen mit Namen + ID und dann über die beiden
Tabellen mit Indices joinen, dann joinst du zwar über INTs, musst aber nicht über die
varchars gehen. Je nach Layout sollte das wesentlich besser funktionieren.

Dann zum sortieren: ich würde nämlich mal bei der hohen CPU Load davon ausgehen dass
die durch das sortieren verursacht wird. (Floatoperationen)... Speicher doch alle Werte als Cents ab, dann musst du keine Floats verwenden und einfach im Skript beim darstellen kurz durch 100 dividieren. (Wobei ich keine Ahnung hab, wie gut SQL bei Decimals skaliert).

Wie siehts mit deinem Resultset aus, wie gross ist das im Schnitt?

Gruss,

Out

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-07 16:33

Also 5 Querys pro Sekunde ist ein Witz, und 500k Einträge sollte mysql mit links erledigen... (es sei denn mysql 3 große Tabellen Bug)

Code: Select all

Uptime:                 97 days 17 hours 56 min 22 sec

Threads: 25  Questions: 1249827497  Slow queries: 6729  Opens: 147426  Flush tables: 1  Open tables: 256  Queries per second avg: 147.989
Bei einem 2800 CPU, und teilweise sehr komplizierten Querys mit etlichen Joins, order by, group by, having, usw, und zwar auch auf Tabellen mit teilweise 1 Mio Einträgen und einer Größe > 1 GB.

Ich vermute, dass deine sehr langsamen Querys keine guten Indeces haben, dies könntest du ja mal mit EXPLAIN vor dem Query testen.

rootserver
Posts: 18
Joined: 2004-06-02 21:30
Location: Berlin

Re: MySQL und Tabelle > 500.000 Einträge

Post by rootserver » 2004-06-07 16:58

Nein, also 500.000 Einträge erledigt MySQL wirklich noch im Schlaf. Bei der MySQL AB gibt es auch die Aussage, dass es auch bei > 10 Mio. Einträgen mit einem normalen Server noch klappen sollte.

Generell gilt (wie oben schon gesagt): DB-Struktur immer durchdenken, einen Index richtig anlegen und alles überschüssige vermeiden (Volltextsuche bspw. lieber über zusätzliche Worttabelle realisieren).

Aber ein Dump der Tabellenstruktur + ein paar Queries wären zur Analyse des Problems wirklich nicht schlecht.

odysseus
Posts: 115
Joined: 2003-02-07 10:21

Re: MySQL und Tabelle > 500.000 Einträge

Post by odysseus » 2004-06-07 17:04

Metrax wrote:MySQL ist nicht für solche Massen ausgelegt. Versuchs mal mit PostgreSQL.
Sorry, aber dieser Kommentar ist reiner "Bullshit".
Ich habe z.B. eine Tabelle mit ca. 14.000.000 Einträgen und der Server geht trotz ständigen Zugriffen darauf nicht in die Knie.

@ Grafzahl:
Zuerst sollte man hier MySQL 4 installieren und den Query Cache einschalten.
Poste man die Tabellenstruktur und die Queries, die darauf ausgeführt werden. Sonst kann man dir hier nicht weiterhelfen. :)

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-07 17:09

Odysseus wrote: Sorry, aber dieser Kommentar ist reiner "Bullshit".

@ Grafzahl:
Zuerst sollte man hier MySQL 4 installieren und den Query Cache einschalten.
Poste man die Tabellenstruktur und die Queries, die darauf ausgeführt werden. Sonst kann man dir hier nicht weiterhelfen. :)
Sorry, auch nicht besser, bzw. nicht Sinnvoll.

Bei 5 (!) Querries pro Sekunde einen Query Cache? Wo issn da der Sinn?
Die Performance wird wohl auch bei 3 Abfragen / Sekunde nicht besser.

MySQL 4 kann gegen ein schlechtes Tabellendesign auch nichts machen.
(Wie ich schon gesagt hab: varchar[] Index und order by Decimal spricht
schon dafür, dann vielleicht noch ein "like '%kondom%'" und tot ist die
DB).

Dem letzten Teil deines Postings stimme ich allerdings zu. (Oben schon geschrieben).


Gruss,

Out, der den ganzen Tag mit DBs arbeitet.

[edit]
Kleiner Nachtrag:
varchar[] Index aufbauen kostet viel Zeit, und wenn da dauernd Daten reinkommen muss
jedes mal der Index neu gebaut werden, allein das ist bei so ner grossen Tabelle wahrscheinlich
ein riesiger Flaschenhals.
[/edit]

grafzahl
Posts: 19
Joined: 2002-09-11 19:39

Re: MySQL und Tabelle > 500.000 Einträge

Post by grafzahl » 2004-06-07 17:39

So, hier ist der Dump der Tabelle Artikel:

Code: Select all

CREATE TABLE `Artikel` (
  `Shopnum` int(11) NOT NULL default '0',
  `Titel` varchar(50) NOT NULL default '',
  `Stop` int(11) NOT NULL default '0',
  `Preis` decimal(11,2) NOT NULL default '0.00',
  `Gebote` int(4) NOT NULL default '0',
  `URL` varchar(100) NOT NULL default '',
  `BildURL` varchar(100) NOT NULL default '',
  KEY `Titel` (`Titel`)
) TYPE=MyISAM;
und hier eine Abfrage aus der "Schnellsuche" mit dem Begriff "Test":

Code: Select all

SELECT Artikel.Titel,Artikel.Stop,Artikel.Preis,Artikel.Gebote,Artikel.URL,Shop.Shopname FROM Artikel,Shop WHERE Artikel.Stop > 1086624990 AND Artikel.Shopnum = Shop.shNummer AND (Titel LIKE '% test %' OR Titel LIKE 'test %' OR Titel LIKE '% test') ORDER BY Artikel.Stop LIMIT 0,50
Zur Info: shNummer ist in der Tabelle Shops PRIMARY KEY

@OutofBound:
Die Querries sieht man nur wenn man gerade eine offene Anfrage erwischt. Die DB ist nicht unten gewesen.
Logs sind abgeschaltet. Eigentlich mache ich auf diese Tabelle nur ein Querry bei der Suchanfrage. Zwischendurch wird aber mal ein oder zwei COUNT(*) als Information zur Artikelanzahl gefragt.

Das mit dem joinen klingt zwar nett ist aber nicht realisierbar. Wenn jemand z.B. Ixus eingibt sollen alle Artikel nach Preis sortiert kommen die auch "Ixus" als eigenständiges Wort beinhalten.

Mit den JOINS hatte ich mal in umgekehrter Methode probiert. Ich wollte alle Shops listen mit deren Anzahl von Artikeln.

Code: Select all

SELECT Shopname,COUNT(*) FROM Shop LEFT JOIN (Shop.shNummer = Artikel.Shopnum) ON Artikel GROUP BY Shopname
Das hat ewig gedauert und ich habe es umfunktioniert. Nun wird beim nächtlichen Artikelimport die Artikel mittel $i++ gezählt und in die Tabelle zum entspechenden Shop geupdated.

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-07 17:49

Wie schaut die Tabelle Shop aus?

Auf diese beiden Spalten solltest du unbedingt einen index legen:

Artikel.Shopnum sowie Shop.shNummer (zu 99% die Lösung deines Problems)

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-07 18:03

Grafzahl wrote:So, hier ist der Dump der Tabelle Artikel:

Code: Select all

CREATE TABLE `Artikel` (
  `Shopnum` int(11) NOT NULL default '0',
  `Titel` varchar(50) NOT NULL default '',
  `Stop` int(11) NOT NULL default '0',
  `Preis` decimal(11,2) NOT NULL default '0.00',
  `Gebote` int(4) NOT NULL default '0',
  `URL` varchar(100) NOT NULL default '',
  `BildURL` varchar(100) NOT NULL default '',
  KEY `Titel` (`Titel`)
) TYPE=MyISAM;
Kein Index, deshalb jedes mal ein Tablescan.
und hier eine Abfrage aus der "Schnellsuche" mit dem Begriff "Test":

Code: Select all

SELECT Artikel.Titel,Artikel.Stop,Artikel.Preis,Artikel.Gebote,Artikel.URL,Shop.Shopname FROM Artikel,Shop WHERE Artikel.Stop > 1086624990 AND Artikel.Shopnum = Shop.shNummer AND (Titel LIKE '% test %' OR Titel LIKE 'test %' OR Titel LIKE '% test') ORDER BY Artikel.Stop LIMIT 0,50
Zur Info: shNummer ist in der Tabelle Shops PRIMARY KEY
Erstmal readability: ;)
select a.titel, a.top, a.preis, a.gebote, a.url from artikel a where bla bla bla

Der join passt, aber Index für beide angeben... wenn du immer über stop gehst, auch
nen Index drauf, dann brauchst du den auf a.shopnum evtl. nicht mehr.
Dann die Suche... '%irgendwas' ist immer böse, da Tablescan, der Optimizer kann sowas
nicht verarbeiten. 'irgendwas%' kann der Optimizer verarbeiten, die anderen Kombinationen nicht. Brauchst du die Leerzeichen vor und nach "test" wirklich?
Wenn du das Produktiv nutzst wird dir auch eine Sybase oder Oracle ziemlich schnell
abkacken.
@OutofBound:
Die Querries sieht man nur wenn man gerade eine offene Anfrage erwischt. Die DB ist nicht unten gewesen.
Ja, ich hatte gehofft ein paar aktive Querries zu sehen, die Live verwendet werden.
Logs sind abgeschaltet. Eigentlich mache ich auf diese Tabelle nur ein Querry bei der Suchanfrage. Zwischendurch wird aber mal ein oder zwei COUNT(*) als Information zur Artikelanzahl gefragt.
Das mit dem joinen klingt zwar nett ist aber nicht realisierbar. Wenn jemand z.B. Ixus eingibt sollen alle Artikel nach Preis sortiert kommen die auch "Ixus" als eigenständiges Wort beinhalten.
Ã?ehm, sowas geht durchaus. Kann man über m-n Beziehungen lösen mit
Schlagwort- Indices.
Mit den JOINS hatte ich mal in umgekehrter Methode probiert. Ich wollte alle Shops listen mit deren Anzahl von Artikeln.

Code: Select all

SELECT Shopname,COUNT(*) FROM Shop LEFT JOIN (Shop.shNummer = Artikel.Shopnum) ON Artikel GROUP BY Shopname
select s.shopname, count(*) from shop s, artikel a where s.shNummer = a.Shopnum group by s.shopname

Wenn das zu lange dauert, dann fehlen Indices.
Das hat ewig gedauert und ich habe es umfunktioniert. Nun wird beim nächtlichen Artikelimport die Artikel mittel $i++ gezählt und in die Tabelle zum entspechenden Shop geupdated.
Setz ein paar Indices, wirf das Mitzählen weg und mach einen schlagwortindex, dann
sollte dein Problem gelöst sein. D

Bsp:

Tbl. words
[id] Numeric[10]
[word] varchar[50]

Tbl artikelmatrix
[artikelid] Numeric[10]
[wordid] Numeric[10]

Tbl.
artikel
[id] Numeric [10]
[beschreibung] varchar[100]
[etc]

Und dann ein select * from words w, artikelmatrix m, artikel a where w.id = m.wordid and m.artikelid = a.id and w.word like 'luxus'

Beim einfügen von Artikeln splittest du die Beschreibung und trägst die Wörter die noch nicht vorhanden sind in die Tbl. words ein, wenn schon vorhanden nutzt du die ID davon. Dann trägst du die Artikel in die artikelmatrix mit den Wörtern ein, fertig.
Beim austragen von Artikeln dann einfach ein delete from artikelmatrix where artikelid = bla machen und das Ding ist aus der Suche ausgetragen.

Da würde ich dann Indices auf die beiden artikelmatrix IDs legen, und auf artikel.id und words.id, und dann wirste staunen wie schnell das rödelt. ;)

Wenn es wirklich viele Wörter sind, kannst du evtl. noch nen Index auf die eigentlichen
Wörter in words legen, aber ich denke das ist aber nur durch messen zu beurteilen.

Gruss,

Out

PS: Alles in Allem: Hab ichs nicht gesagt? ;) ;)

PPS: Nur grad so ausm Kopf zusammengeschludert, man muss natürlich noch einiges mehr
beachten. Datenbankdesign ist sowohl Können als auch Kunst, deshalb muss jede Lösung
individuell betrachtet werden. Ich wollte nur nachweisen, dass man Wörtersuchen noch wesentlich effizienter gestalten kann als mit '%irgendwas%'.

grafzahl
Posts: 19
Joined: 2002-09-11 19:39

Re: MySQL und Tabelle > 500.000 Einträge

Post by grafzahl » 2004-06-07 18:45

Da hätte ich dann noch ein paar Fragen zur Wortliste, ausprobieren werde ich es morgen. Ich bin schon froh,wenn ich nicht auf postgresql umsteigen muß.

Das beim Artikelimport die Beschreibung nach Wörtern gesplittet wird und die Wörter in die Tabelle Word geschrieben werden ist ja kein Ding.

Wie mache ich aber ohne vorheriges SELECT der Tabelle Word klar, daß sie nur Wörter annehmen soll, die noch nicht da sind ?

In Tabelle Artikel muß als Feld "id" ein INT(11) AUTO_INCREMENT als PRIMARY KEY oder nur als INDEX eingefügt werden ?

Weitere Fragen werden bestimmt noch aufkommen.
Danke erstmal.

tyberius prime
Posts: 31
Joined: 2003-07-09 11:01

Re: MySQL und Tabelle > 500.000 Einträge

Post by tyberius prime » 2004-06-07 18:58

"like '%irgendwas%'... und was der Optimizer damit macht, will keiner wirklich wissen.
Wollen vieleicht nicht, aber sollen - er benutzt naemlich ueberhaupt keine Indices.

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-07 19:57

Wie gesagt, ich vermute immer noch, dass das größte Problem ist, dass er bei dem JOIN (Artikel.Shopnum = Shop.shNummer) bei beiden Tabellen keine Indeces hat, und deshalb dieser ewig lange dauert.

Natürlich ist es richtig, dass LIKE '%foo' ebenfalls sehr aufwendig ist, ich denke aber nicht, dass das das "Hauptproblem" ist.

Deshalb einfach mal einen Index auf diese beiden Spalten setzen.

grafzahl
Posts: 19
Joined: 2002-09-11 19:39

Re: MySQL und Tabelle > 500.000 Einträge

Post by grafzahl » 2004-06-08 14:46

So, ich habe alle Indexe wie besprochen gesetzt und siehe da, ES KLAPPT !!!

Die Datenbank läuft nun bei knapp 570.000 Artikel, die Abfrage funktioniert. Danke an alle.

Nur noch zum Thema Artikelmatrix:

Ich habe nun eine Artikelmatrix erstellt. Dauer bei 200.000 Artikel ca. 2 Stunden. Gucken in Tabelle Words ob Wort da ist, wenn ja WortID, wenn nein INSERT und insertid holen, anschließend INSERT ArtikelID und WortID in Tabelle Artikelmatrix.

Ergebiss: ca. 30.000 Einträge in Words und ca. 900.000 Einträge in Artikelmatrix.

Wie soll das denn bei meinen geplanten 4.000.000 Artikeln aussehen ? Da würden ja ca. 20.000.000 Einträge in der Artikelmatrix stehen !!! Da die Artikel jede Nacht aus der Datenbank gelöscht und neu importiert werden, ist das für mich zeitlich überhaupt nicht realisierbar. Da müßte ich schon einen zweiten Server haben, der sich nur mit der Artikelmatrix beschäftigt.

Nunja, da denke ich, daß ich lieber bei der "LIKE" Geschichte bleibe, bis ich an die Grenzen stoße und dann lieber einen leistungstärkeren Server miete.

Trotzdem Danke für den Tipp mit der Matrix. Die werde ich bestimmt mal in andere Projekte einsetzen können (Shopsystem, etc.).

Gruß Axel

outofbound
Posts: 470
Joined: 2002-05-14 13:02
Location: Karlsruhe City

Re: MySQL und Tabelle > 500.000 Einträge

Post by outofbound » 2004-06-08 15:44

Grafzahl wrote:So, ich habe alle Indexe wie besprochen gesetzt und siehe da, ES KLAPPT !!!
Dann ist ja gut. ;)
Die Datenbank läuft nun bei knapp 570.000 Artikel, die Abfrage funktioniert. Danke an alle.
Und das ganz ohne Umstellen ;)
Ich habe nun eine Artikelmatrix erstellt. Dauer bei 200.000 Artikel ca. 2 Stunden. Gucken in Tabelle Words ob Wort da ist, wenn ja WortID, wenn nein INSERT und insertid holen, anschließend INSERT ArtikelID und WortID in Tabelle Artikelmatrix.
Das finde ich interessant. 27 Artikel pro Sekunde? Kannst du das mal timen, was da so
lange dauert?
Ergebiss: ca. 30.000 Einträge in Words und ca. 900.000 Einträge in Artikelmatrix.
Das war zu erwarten ;)
Wie soll das denn bei meinen geplanten 4.000.000 Artikeln aussehen ? Da würden ja ca. 20.000.000 Einträge in der Artikelmatrix stehen !!! Da die Artikel jede Nacht aus der Datenbank gelöscht und neu importiert werden, ist das für mich zeitlich überhaupt nicht realisierbar. Da müßte ich schon einen zweiten Server haben, der sich nur mit der Artikelmatrix beschäftigt.
Warum löschst du denn die Daten jedes mal komplett und importierst die neu?
Mir kommt das komisch vor.

/*5 Mio mal ca 30 Worte pro Artikel == 150 Mio. Einträge. */
Edit: Vergesst das ;) ;) ;)

Ich würde mal sage, 50 % davon sind Worte wie "der/die/das/eine/ein/in/an/auf"... nach
sowas sollte man natürlich nicht suchen lassen ;)

Wie siehts mit Gross/Kleinschreibung aus, das hast du hogffentlich abgefangen? ;)

Setz doch den varchar[] auf Uniqe, dann dürfteste dir auch noch etwas Zeit sparen. ;)

Gruss,

Out

kase
Posts: 1031
Joined: 2002-10-14 22:56

Re: MySQL und Tabelle > 500.000 Einträge

Post by kase » 2004-06-08 16:13

Kannst du mal erzählen, welche Indeces du jetzt genau gesetzt hast?

Meine beiden, die ich dir vorgeschlagen habe, und noch weitere?

Auf jeden Fall musst du dir unbedingt für die Zukunft merken:

Wenn du 2 Tabellen hast, die du miteinander "joinst" (also tabelle1.id = tabelle2.artikel oder so irgednwas in der Art), dann musst du UNBEDINGT auf beide Join-Spalten einen Index legen. Wie gesagt ein Join ohne Index ist Selbstmord. Hier sind leichte Vorteile bei anderen Datenbanken, zB PostgreSQL, diese setzen bei sowas automatisch einen Index. (was ich allerdings wieder doof finde, da der Index immer nur temporär ist, also bei jedem Join neu erstellt wird, aber trotzdem ist das ganze unendlich schneller ... ;) )

tyberius prime
Posts: 31
Joined: 2003-07-09 11:01

Re: MySQL und Tabelle > 500.000 Einträge

Post by tyberius prime » 2004-06-08 19:03

nur um's nochmal zu wiederholen:
bei like '%shu' und like 'shu%' kann MySQL durchaus Indices nutzen.

Wenn aber ein like '%shu%' kommt, muss es alle Datensaetze durchgehen.


PS: Ab Mysql 3.23.23 gibt es die Volltextsuche, die ist recht fix, und macht quasi genau das gleiche wie die Artikelmatrix, nur schneller (weil a) c-code b) muss die Datenbank nicht hin und her schaufeln, um den Index zu erstellen).