codez Posted January 29, 2013 Report Share Posted January 29, 2013 (edited) Pēdējos projektos kaut kā sanāca izmantot Perconu un Mysql ilgi nebija aiztikts, bet šodien sanāca, ka vajadzēja izveidot vienu Mysql tabulu ar 1'000'000 ierakstiem. Tātad vienkāršotā gadījumā, CREATE TABLE `testdb`.`test1` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`val` varchar(8) NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8;Kā redzams, ir izmantots InnoDB un primary_key ir uz id, tika mēģināts arī likt atsevišķi indeksu uz id, tika mēģināts arī myisam. Tas tika mēģināt kā uz windows tā uz Centos. Mysql versija 5.1.X Visos gadījumos viens un tas pats. Tātad izpildot parastu kveriju: SELECT * FROM test1 ORDER BY id LIMIT 500000,10Šāds kverijs izpildās 5 sekundes un uzliekot EXPLAIN var redzēt, ka tiek skenētas 500010 rindas, tātad fullscans.1, 'SIMPLE', 'test1', 'index', '', 'PRIMARY', '4', '', 500010, ''Apjautājos dažiem paziņām un daži teica, ka arī ir nācies ar to sastapties un, ka pie kaut kāda lielāka ierakstu skaita, pēkšņi kveriju izpilde vienkārši saiet sviestā. Nonācām pie versijām: 1) 10% - visiem mums ir līkas rokas un pārāk maz gulētas naktis 2) 20% - bugs 3) 70% - orakle sācis bojāt mysql, lai visi pirktu dārgos maksas produktus. Tātad, varbūt kādam ir kādas versijas, kāpēc šādi notiek? Edited January 29, 2013 by codez Quote Link to comment Share on other sites More sharing options...
marrtins Posted January 29, 2013 Report Share Posted January 29, 2013 (edited) Man šķiet, ka tas bija tāpēc, ka "skrollēšanai" ar LIMIT tas index nemaz netiek izmantots. Kāpēc nē - nezinu. Ā, vēl pamēģini tikai ar "select testdb.id" nevis *. Edited January 29, 2013 by marrtins Quote Link to comment Share on other sites More sharing options...
codez Posted January 29, 2013 Author Report Share Posted January 29, 2013 Nu tas būtu gaužām dīvaini, jo LIMIT tiek izmantots jebkurā vietā, kur ir vajadzība sadalīt lapaspusēs (IMHO). P.S. Uzliku 5.5.X versiju, tas pats. Quote Link to comment Share on other sites More sharing options...
Kasspars Posted January 29, 2013 Report Share Posted January 29, 2013 Man šķiet, ka tas bija tāpēc, ka "skrollēšanai" ar LIMIT tas index nemaz netiek izmantots. Kāpēc nē - nezinu. Ā, vēl pamēģini tikai ar "select testdb.id" nevis *. Nu tā nav! Index tiek izmanots, ja limitē! Tikko pats pamēģināju ar 1010000 ierakstiem un tavs query man izpildās 0.27 sekundēs Man explain izskatās šādi 1 SIMPLE test1 index NULL PRIMARY 4 NULL 500010 Kā tu izsecināji, ka tev tur notiek fullscan? Quote Link to comment Share on other sites More sharing options...
marrtins Posted January 29, 2013 Report Share Posted January 29, 2013 Index tiek izmantot atlaisei/kārtošanai. Pēc tam mysql iterē līdz vajadzīgajiem ierakstiem. Jo vairāk kolonnas, jo lēnāk. Ja tu testēji tikai ar vienu id kolonnu, tad varētu arī būt ātri. Ja pietiekams buffer pool, tad bik ātrāk varētu būt atlasīt tikai id (par cik tas ir indexā un nav jāaiztiek dati) un sajoinot vēlreiz ar to pašu tabulu un ar vajadzīgajiem datiem, vai kaut vai *. Quote Link to comment Share on other sites More sharing options...
codez Posted January 29, 2013 Author Report Share Posted January 29, 2013 Kā tu izsecināji, ka tev tur notiek fullscan?Pie EXPLAIN ir sadaļa rows, kurā norāda, cik rindas tiks noskenētas. Par laikiem, pie 1M ierakstiem šijā testa tabulā man laiks ir 0.29. Pāris sekundes bija īstajā tabulā, kur katrs rows ir ap 1kB liels. Tikko pats pamēģināju ar 1010000 ierakstiem un tavs query man izpildās 0.27 sekundēsArī 0.27 sekundes, lai nolasītu 10 ierakstus ir ļoti lēni. Quote Link to comment Share on other sites More sharing options...
Kasspars Posted January 29, 2013 Report Share Posted January 29, 2013 nu tad iekopē īstās tabulas struktūru! Quote Link to comment Share on other sites More sharing options...
codez Posted January 29, 2013 Author Report Share Posted January 29, 2013 (edited) Mjā, šķiet marrtinam taisnība, ka mysql neizmanto indeku, lai meklētu offsetu. http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down/4502426#4502426 P.S. Tas ir tik tizli <- tas, ka mysql tā dara jeb precīzāk nedara. Edited January 29, 2013 by codez Quote Link to comment Share on other sites More sharing options...
codez Posted January 29, 2013 Author Report Share Posted January 29, 2013 nu tad iekopē īstās tabulas struktūru!Vari pamēģināt val uztaisīt par varchar(1000). Quote Link to comment Share on other sites More sharing options...
marrtins Posted January 29, 2013 Report Share Posted January 29, 2013 Pamēģinājo to kveriju no stackoverflow ar join uz tās pašas tabulas? Quote Link to comment Share on other sites More sharing options...
Kasspars Posted January 29, 2013 Report Share Posted January 29, 2013 (edited) Mjā, šķiet marrtinam taisnība, ka mysql neizmanto indeku, lai meklētu offsetu. http://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down/4502426#4502426 P.S. Tas ir tik tizli <- tas, ka mysql tā dara jeb precīzāk nedara. Par to index un offset vēl var pastrīdēties. Tas laikam atkarīgs no paša mysql, kā viņš tagad izdomās taisīt fullscan vai pēc indeksa. Skaidri zinu, ka problēmas sākas, ja piedžoino tabulu un tad kārto pēc tās lauka, tad gan ideksu neizmanto un sākas fullscans SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.idd ORDER BY table2.val Edited January 29, 2013 by Kasspars Quote Link to comment Share on other sites More sharing options...
codez Posted January 29, 2013 Author Report Share Posted January 29, 2013 Pamēģinājo to kveriju no stackoverflow ar join uz tās pašas tabulas?Tātad pārliku lauku val uz VARCHAR(250) un piepildīju visas rindas ar maks vērtībām. Ierakstu skaits 2^32 =aptuveni 1M. SELECT * FROM test ORDER BY id LIMIT 500000,10 Laiks: 3.7s SELECT t.*FROM (SELECT idFROM test oORDER BY idLIMIT 500000, 10) oJOIN test tON t.id = o.idORDER BY t.id Laiks: 3.5s (principā tik pat) Lai notestētu, vai tiešām tikai primary key indeksa nolasīšanai ir jēga: SELECT id FROM test ORDER BY id LIMIT 500000,10 Laiks: 3.2s Principā dotā metode necik nepalīdzēja. Metode no stackoverflow atbildes.(http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/) Quote Link to comment Share on other sites More sharing options...
Kasspars Posted January 29, 2013 Report Share Posted January 29, 2013 Pamēģini piespiest MySQL izmantot PRIMARY indexu. Jāpaskatās kā precīzi sintakse bija. Tipa FORCE_INDEX Quote Link to comment Share on other sites More sharing options...
marrtins Posted January 29, 2013 Report Share Posted January 29, 2013 Skaidri zinu, ka problēmas sākas, ja piedžoino tabulu un tad kārto pēc tās lauka, tad gan ideksu neizmanto un sākas fullscans Ne vienmēr un ne tik viennozīmīgi. Vnk ja tas mysql analizators izdomās, ka ātrāk būs fullscan, kā index access un tad datu access, tad indexus arī var neizmantot. Gadās, protams, ka kļūdās. codez, cik liels tev id buffer pools (show status like 'innodb%')? Izklausās pārāk maza atšķirība. Quote Link to comment Share on other sites More sharing options...
marrtins Posted January 29, 2013 Report Share Posted January 29, 2013 Pamēģini piespiest MySQL izmantot PRIMARY indexu. Jāpaskatās kā precīzi sintakse bija. Tipa FORCE_INDEX Šis nav tas gadījums. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.