Avatar billede sylvesternielsen Nybegynder
15. maj 2008 - 18:14 Der er 20 kommentarer og
1 løsning

Langsomme querys med BETWEEN

Jeg har en database med næsten 4mill rækker i.

Jeg skal lave nogle opslag med BETWEEN statement.
F.eks. SELECT * FROM `ich` WHERE 12345678 BETWEEN `start_number` AND `end_number`

Et sådan opslag tager ca. 60 sekunder og med 15.000 numre som skal checkes på denne måde, så vil det tage 10-15 dage at køre disse udtræk.

Nogen gode ideér?
Avatar billede arne_v Ekspert
15. maj 2008 - 18:35 #1
Er der index paa start_number og end_number ?

Nej => tilfoej det !
Avatar billede sylvesternielsen Nybegynder
15. maj 2008 - 19:33 #2
Hej Arne,

Ja det er index på start_number og end_number.
Men det er stadigt bare voldsomt sløvt. Er ved at sætte en dedikeret maskine op til opgaven med masser af CPU, RAM og hurtige diske. Måske det kan hjælpe lidt på det også.
Avatar billede arne_v Ekspert
15. maj 2008 - 19:53 #3
Kan du proeve med en EXPLAIN paa query'en ?
Avatar billede arne_v Ekspert
15. maj 2008 - 19:54 #4
Altsaa poste output af EXPLAIN her.
Avatar billede sylvesternielsen Nybegynder
15. maj 2008 - 19:57 #5
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra      |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | ich  | ALL  | NULL          | NULL | NULL    | NULL | 3884299 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
Avatar billede sylvesternielsen Nybegynder
15. maj 2008 - 20:52 #6
Den nye maskine er mindst lige så langsom, selvom den hardware mæssigt er langt bedre.
Måske det er diskene som er begrænsningen!

Hvilken database engine vil være bedst til denne opgave? Lige nu benytter jeg innoDB, men er MyISAM bedre?

Pladsmæssigt er det 747MB data og 613,5MB index.
Avatar billede arne_v Ekspert
16. maj 2008 - 03:06 #7
Jeg tror at det er fordi at den BETWEEN er lidt anderledes.

Prøv:

SELECT *
FROM ich
WHERE start_number <= 12345678 end_number >= 12345678
Avatar billede arne_v Ekspert
16. maj 2008 - 03:06 #8
altså både test tid og EXPLAIN
Avatar billede arne_v Ekspert
16. maj 2008 - 03:07 #9
Jeg glemte AND:

SELECT *
FROM ich
WHERE start_number <= 12345678 AND end_number >= 12345678
Avatar billede sylvesternielsen Nybegynder
16. maj 2008 - 09:53 #10
Den er mindst lige så langsom.

Kan det være fordi den ikke bruger indexet?

mysql> EXPLAIN SELECT * FROM ich WHERE start_number <=43669090 AND end_number >=43669090;
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys          | key  | key_len | ref  | rows    | Extra      |
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | ich  | ALL  | start_number,end_number | NULL | NULL    | NULL | 3765149 | Using where |
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM ich WHERE start_number <=12345678 AND end_number >=12345678;
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys          | key          | key_len | ref  | rows | Extra      |
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
|  1 | SIMPLE      | ich  | range | start_number,end_number | start_number | 8      | NULL |    1 | Using where |
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
1 row in set (0.00 sec)
Avatar billede sylvesternielsen Nybegynder
16. maj 2008 - 09:56 #11
mysql> EXPLAIN SELECT * FROM ich WHERE 43669090 BETWEEN start_number AND end_number;
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys          | key  | key_len | ref  | rows    | Extra      |
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | ich  | ALL  | start_number,end_number | NULL | NULL    | NULL | 3753234 | Using where |
+----+-------------+-------+------+-------------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM ich WHERE 12345678 BETWEEN start_number AND end_number;
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys          | key          | key_len | ref  | rows | Extra      |
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
|  1 | SIMPLE      | ich  | range | start_number,end_number | start_number | 8      | NULL |    1 | Using where |
+----+-------------+-------+-------+-------------------------+--------------+---------+------+------+-------------+
1 row in set (0.00 sec)
Avatar billede sylvesternielsen Nybegynder
16. maj 2008 - 12:23 #12
Jeg har nu testet med en oracle database også, med samme resultat.

Det ser ud som om jeg mister index når jeg smider 2 parametre på.

Ingen ventetid på SELECT * FROM ich WHERE start_number <=12345678 eller SELECT * FROM ich WHERE start_number >=12345678

Men er det SELECT * FROM ich WHERE start_number <=12345678 AND end_number >=12345678;
Så det ser ud som om at jeg mister mit index ved 2 parametrer.
Avatar billede morw Nybegynder
16. maj 2008 - 14:21 #13
Hvad med at lave et sammensat index over begge felter
Avatar billede sylvesternielsen Nybegynder
16. maj 2008 - 16:16 #14
Hvordan gør jeg det?
Avatar billede morw Nybegynder
16. maj 2008 - 17:05 #15
ALTER TABLE `hest` ADD INDEX ( `felt2` , `felt1` )
Avatar billede morw Nybegynder
16. maj 2008 - 17:09 #16
eller syntax hvis du selv vil give det navn:

ALTER TABLE `hest` ADD INDEX `nytIndex` ( `felt1` , `felt2` )
Avatar billede sylvesternielsen Nybegynder
02. april 2009 - 20:46 #17
Smid et svar for point. :-)
Avatar billede arne_v Ekspert
02. april 2009 - 20:58 #18
hvem ?
Avatar billede sylvesternielsen Nybegynder
02. april 2009 - 21:12 #19
Ja, det er jo så lige det.. Jeg fik aldrig løst problemet, da projektet blev nedlagt.. Men hvis der er nogen af jer som vil have pointene er det bare at smide et svar. =)
Avatar billede arne_v Ekspert
03. april 2009 - 00:48 #20
ikke mig
Avatar billede sylvesternielsen Nybegynder
03. april 2009 - 07:56 #21
Så lukker og slukker jeg..
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester