Schrift
[thread]3463[/thread]

Effiziente SELECTs in MySQL: Insertion order determinieren? (Seite 2)



<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten
Oesi50
 2004-06-08 18:31
#32224 #32224
User since
2004-05-15
33 Artikel
BenutzerIn
[default_avatar]
TIMESTAMP ist UNSIGNED INT

@ptk

wenn Du einen Index hast, kann min(..) wegfallen.
Was sagt denn EXPLAIN dazu?\n\n

<!--EDIT|Oesi50|1086705360-->
ptk
 2004-06-08 18:33
#32225 #32225
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
[quote=Thorium,08.06.2004, 16:24]Wie gesagt.
Leg ein weiteres attribut mit dem Namen "int_time" mit Unsigned INT an und speichere die Dati da rein. Dann kannst du einen Index drüberlegen und bist viel, viel schneller.[/quote]
Ich werd's versuchen, auch wenn ich keine grosse Hoffnung hege. Der Table-Scan muss ja trotzdem gemacht werden.
Gast Gast
 2004-06-08 19:00
#32226 #32226
[quote=ptk,08.06.2004, 16:06][quote=Dieter,08.06.2004, 15:22][quote=Oesi50,08.06.2004, 14:54]@Dieter
Das würde ich nicht machen, da könnte Dir der Speicher platzen.
[/quote]
Nööö ...
ich lese sowas immer Step-By-Step aus (max. 1000 Datensätze per Durchlauf) und damit wird selbst der kleinste Speicher fertig :)[/quote]
Wuerdest du LIMIT verwenden? Ich versuche es gerade mit
Code: (dl )
1
2
3
4
5
6
7
8
9
10
$i=0;
while(1) {
   warn $i;
   $sql = qq{SELECT accesslog_id FROM accesslog WHERE accessdate >= "2004-01-01 00:00:00" LIMIT $i,1000};
   $sth = $g_dbh->prepare($sql);
   $sth->execute;
   $x = $sth->fetchall_arrayref;
   last if not @$x;
   $i+=1000;
}'

Am Anfang werden die Debugpoints noch schnell ausgedruckt, aber je groesser $i wird, desto langsamer wird das SELECT. Und wie es aussieht, wird dieser Code laenger brauchen als die Variante mit MIN(...).[/quote]
Nein - LIMIT kann nicht funktionieren weil dann immer wieder beim ersten Satz der Tabelle angefangen wird - also würdest Du dann immer die selben Rückgabewerte erhalten.

Entweder ermittelst den Focus der zuletzt ausgeführten Operation (und machst an der nächsten Stelle weiter) oder Du zählst die Durchläufe und läßt alles was vor dem letzen Durchlauf schon gelesen wurde ($cnt * 1000) in eine 'Leervariable' laufen (das ist teuer).
ptk
 2004-06-08 20:10
#32227 #32227
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
@dieter: Ich habe LIMIT $i, 1000 verwendet, also mit variablem Startwert.

Dein Vorschlag mit dem Weitermachen an der alten Stelle funktioniert zwar, aber scheint aehnlich langsam zu sein wie die Variante mit SELECT min(...).
renee
 2004-06-08 23:10
#32228 #32228
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
wie wär's mit [sql]SELECT accesslog_id from accesslog WHERE accessdate >= "2004-01 -01 00:00:00" ORDER BY accesslog DESC LIMIT 0, 1 ;[/sql]
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
ptk
 2004-06-09 13:17
#32229 #32229
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
[quote=renee,08.06.2004, 21:10]wie wär's mit [sql]SELECT accesslog_id from accesslog WHERE accessdate >= "2004-01 -01 00:00:00" ORDER BY accesslog DESC LIMIT 0, 1 ;[/sql][/quote]
Das muss wohl "ASC" statt "DESC" sein. Trotzdem das gleiche Ergebnis:
Code: (dl )
1 row in set (4 min 32.05 sec)


@thorium: int_time bringt auch keinen grossen Geschwindigkeitsgewinn:
Code: (dl )
1
2
mysql> select min(accesslog_id) from accesslog where int_time >1080770400;     
1 row in set (4 min 20.73 sec)
int_time ist als KEY angelegt.

@oesi50: Laut EXPLAIN scheint es immer einen Table-Scan zu geben. Hier die verschiedenen Varianten:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> explain select min(accesslog_id) from accesslog where int_time >1080770400;
+-----------+------+---------------+------+---------+------+----------+------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-----------+------+---------------+------+---------+------+----------+------------+
| accesslog | ALL | int_time | NULL | NULL | NULL | 13563083 | where used |
+-----------+------+---------------+------+---------+------+----------+------------+
1 row in set (0.01 sec)

mysql> explain select accesslog_id from accesslog where int_time >1080770400 order by accesslog_id LIMIT 0,1;
+-----------+-------+---------------+----------+---------+------+----------+--------------

--------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-----------+-------+---------------+----------+---------+------+----------+--------------

--------------+
| accesslog | range | int_time | int_time | 5 | NULL | 13563083 | where used; Using filesort |
+-----------+-------+---------------+----------+---------+------+----------+--------------

--------------+
1 row in set (0.00 sec)
Oesi50
 2004-06-09 14:10
#32230 #32230
User since
2004-05-15
33 Artikel
BenutzerIn
[default_avatar]
was gibt das?

explain select accesslog_id from accesslog where int_time >1080770400 LIMIT 0,1;

und wie lange dauert es?

Wenn die Spalte einen Index hat, geht es auch ohne ORDER BY
Oesi50
 2004-06-09 14:40
#32231 #32231
User since
2004-05-15
33 Artikel
BenutzerIn
[default_avatar]
ich habe das jetzt mal getestet:

mit 160775 Zeilen und dieser Struktur

Code: (dl )
1
2
3
4
5
6
7
CREATE TABLE s_ticklist_ETR (
sym char(5) NOT NULL default '',
zeit timestamp(14) NOT NULL,
kurs mediumint(8) unsigned NOT NULL default '0',
volumen mediumint(8) unsigned NOT NULL default '0',
KEY zeit (zeit)
) TYPE=MyISAM PACK_KEYS=1 COMMENT='Tickerliste';

Das ergibt bei mir diese Ergebnisse:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SELECT *
FROM s_ticklist_ETR
WHERE zeit > '2004-04-08-12:22:06'
ORDER BY zeit
LIMIT 0 , 1

0.0024 sek

EXPLAIN

table type possible_keys key key_len ref rows Extra
s_ticklist_ETR range zeit zeit 4 NULL 5008 Using where

-------------------------------------------------------------------------------

SELECT *
FROM s_ticklist_ETR
WHERE zeit > '2004-04-08-12:22:06'
LIMIT 0 , 1

0.0019 sek

EXPLAIN

table type possible_keys key key_len ref rows Extra
s_ticklist_ETR range zeit zeit 4 NULL 5008 Using where


ohne Index
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
SELECT *
FROM s_ticklist_ETR
WHERE zeit > '2004-04-08-12:22:06'
ORDER BY zeit
LIMIT 0 , 1

0.2560 sek

EXPLAIN

table type possible_keys key key_len ref rows Extra
s_ticklist_ETR range NULL NULL NULL NULL 160774 Using where; Using filesort



Ich wundere mich auch über deine Schlüssellänge 5, UNSIGNED INT hat doch nur 4 Byte?\n\n

<!--EDIT|Oesi50|1086778267-->
renee
 2004-06-09 15:01
#32232 #32232
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
bringt ein [sql]DISTINCT[/sql] was??

[sql]SELECT DISTINCT accesslog_id from accesslog WHERE accessdate >= "2004-01 -01 00:00:00" ORDER BY accesslog ASC;[/sql]
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Oesi50
 2004-06-09 15:21
#32233 #32233
User since
2004-05-15
33 Artikel
BenutzerIn
[default_avatar]
[quote=renee,09.06.2004, 13:01]bringt ein [sql]DISTINCT[/sql] was??

[sql]SELECT DISTINCT accesslog_id from accesslog WHERE accessdate >= "2004-01 -01 00:00:00" ORDER BY accesslog ASC;[/sql][/quote]
nein das bringt nichts, das wird sogar langsamer.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
ohne DISTINCT
EXPLAIN

table type possible_keys key key_len ref rows Extra
s_ticklist_ETR range zeit zeit 4 NULL 5008 Using where

mit DISTINCT

EXPLAIN

table type possible_keys key key_len ref rows Extra
s_ticklist_ETR range zeit zeit 4 NULL 5008 Using where; Using temporary
<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten



View all threads created 2004-06-08 16:02.