Jump to content
php.lv forumi

Mysql izvēlās neefektīvus izpildes ceļus.


codez

Recommended Posts

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 by codez
Link to comment
Share on other sites

  • Replies 36
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

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?

Link to comment
Share on other sites

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 *.

Link to comment
Share on other sites

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ēs

Arī 0.27 sekundes, lai nolasītu 10 ierakstus ir ļoti lēni.
Link to comment
Share on other sites

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 by Kasspars
Link to comment
Share on other sites

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/)

Link to comment
Share on other sites

 

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.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...