[ maroon984 @ 26.02.2015. 13:08 ] @
Pozdrav svima.
Imam problem sa sporim SELECT upitom. Nekada se izvrši za 30s, a nekada mu treba 2-3min.

Upit je:

Code:
SELECT ID_log, gtime, uredjaj, event FROM log FORCE INDEX (gtime_uredjaj_idx) WHERE gtime BETWEEN '2014-10-10' AND '2014-10-30' AND uredjaj=1234;


Explain za ovaj upit je:

Code:

+----+-------------+-------+-------+-------------------+-------------------+---------+------+----------+-------------+
| id | select_type | table | type  | possible_keys     | key               | key_len | ref  | rows     | Extra       |
+----+-------------+-------+-------+-------------------+-------------------+---------+------+----------+-------------+
|  1 | SIMPLE      | log   | range | gtime_uredjaj_idx | gtime_uredjaj_idx | 7       | NULL | 10683481 | Using where |
+----+-------------+-------+-------+-------------------+-------------------+---------+------+----------+-------------+


Sve vrijeme SELECT zašteka na State: Sending data.
Ima li neki buffer ili nešto slično da se poveća, da ovo ubrzam malo?

MySQL je 5.5.24, 32G RAM

[ bogdan.kecman @ 26.02.2015. 13:34 ] @
daj create
[ maroon984 @ 26.02.2015. 13:46 ] @
Code:
CREATE TABLE `log` (
  `ID_log` bigint(19) unsigned NOT NULL AUTO_INCREMENT,
  `Uredjaj` mediumint(8) unsigned NOT NULL,
  `Gtime` timestamp NOT NULL DEFAULT '1971-01-01 00:00:00' COMMENT 'Vrijeme kada je kreirana poruka',
  `Event` tinyint(3) unsigned DEFAULT NULL,
  `TempSensor1` float DEFAULT NULL,
  `TempSensor2` float DEFAULT NULL,
  `TempSensor3` float DEFAULT NULL,
  `TempSensor4` float DEFAULT NULL,
  `Tmp1` tinyint(4) DEFAULT NULL,
  `Tmp2` tinyint(3) unsigned DEFAULT NULL,
  `Tmp3` int(10) unsigned DEFAULT NULL,
  `Tmp4` float unsigned DEFAULT NULL,
  PRIMARY KEY (`ID_log`,`Gtime`),
  KEY `gtime_uredjaj_idx` (`Gtime`,`Uredjaj`)
) ENGINE=InnoDB AUTO_INCREMENT=294105490 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
/*!50100 PARTITION BY RANGE (unix_timestamp(gtime))
(PARTITION p0 VALUES LESS THAN (1388530800) ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (1391209200) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (1393628400) ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN (1396303200) ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN (1398895200) ENGINE = InnoDB,
 PARTITION p5 VALUES LESS THAN (1401573600) ENGINE = InnoDB,
 PARTITION p6 VALUES LESS THAN (1404165600) ENGINE = InnoDB,
 PARTITION p7 VALUES LESS THAN (1406844000) ENGINE = InnoDB,
 PARTITION p8 VALUES LESS THAN (1409522400) ENGINE = InnoDB,
 PARTITION p9 VALUES LESS THAN (1412114400) ENGINE = InnoDB,
 PARTITION p10 VALUES LESS THAN (1414796400) ENGINE = InnoDB,
 PARTITION p11 VALUES LESS THAN (1417388400) ENGINE = InnoDB,
 PARTITION p12 VALUES LESS THAN (1420066800) ENGINE = InnoDB,
 PARTITION p13 VALUES LESS THAN (1422745200) ENGINE = InnoDB,
 PARTITION p14 VALUES LESS THAN (1425164400) ENGINE = InnoDB,
 PARTITION p15 VALUES LESS THAN (1427839200) ENGINE = InnoDB,
 PARTITION p16 VALUES LESS THAN (1430431200) ENGINE = InnoDB,
 PARTITION p17 VALUES LESS THAN (1433109600) ENGINE = InnoDB,
 PARTITION p18 VALUES LESS THAN (1435701600) ENGINE = InnoDB,
 PARTITION p19 VALUES LESS THAN (1438380000) ENGINE = InnoDB,
 PARTITION p20 VALUES LESS THAN (1441058400) ENGINE = InnoDB,
 PARTITION p21 VALUES LESS THAN (1443650400) ENGINE = InnoDB,
 PARTITION p22 VALUES LESS THAN (1446332400) ENGINE = InnoDB,
 PARTITION p23 VALUES LESS THAN (1448924400) ENGINE = InnoDB,
 PARTITION p24 VALUES LESS THAN (1451602800) ENGINE = InnoDB)
[ bogdan.kecman @ 26.02.2015. 13:53 ] @
ok, daj i explain partitions
i sta kaze explain partitions kad izbacis taj force index
[ maroon984 @ 26.02.2015. 13:58 ] @
Code:
+----+-------------+-------+------------+-------+-------------------+-------------------+---------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys     | key               | key_len | ref  | rows     | Extra       |
+----+-------------+-------+------------+-------+-------------------+-------------------+---------+------+----------+-------------+
|  1 | SIMPLE      | log   | p10        | range | gtime_uredjaj_idx | gtime_uredjaj_idx | 7       | NULL | 10749592 | Using where |
+----+-------------+-------+------------+-------+-------------------+-------------------+---------+------+----------+-------------+
1 row in set (0.05 sec)
[ bogdan.kecman @ 26.02.2015. 14:04 ] @
ok problem ti je ovde

KEY `gtime_uredjaj_idx` (`Gtime`,`Uredjaj`)

kada kazes between gtim uredjaj tu vise ne moze da se koristi, prebaci taj index da bude

KEY `gtime_uredjaj_idx` (`Uredjaj`, `Gtime`)

i trebalo bi mnogo bolje da radi
[ maroon984 @ 26.02.2015. 14:29 ] @
Da li postoji neka "prekompozicija" SELECT upita, da sa postojećim INDEX-ima dobijem željeni rezultati?

Problem sa mijenjanjem INDEX-a je što mi drop index i create index traju dugo, što znači da servis mora biti offline to isto vrijeme.
Ako ne, pokušaću sa tvojim rješenjem.

Da li možeš da mi objesniš koja je razlika između KEY `gtime_uredjaj_idx` (`Uredjaj`, `Gtime`) i (`Gtime`,`Uredjaj`)?

[ bogdan.kecman @ 26.02.2015. 14:38 ] @
Citat:
maroon984: Da li postoji neka "prekompozicija" SELECT upita, da sa postojećim INDEX-ima dobijem željeni rezultati?

ne

Citat:
maroon984:
Problem sa mijenjanjem INDEX-a je što mi drop index i create index traju dugo, što znači da servis mora biti offline to isto vrijeme.
Ako ne, pokušaću sa tvojim rješenjem.

napravis drugu tabelu sa istom strukturom ali pravilnim indexom
uradis insert select iz prve tabele
uradis rename stare tabele i temp i nove u staru
bitno je samo dakle da tokom tog kopiranja zalokujes staru za pisanje, bice ti dostupna ali read only .. to je najbolje sto mogu da ti ponudim

ili samo kreiras novi index b,a i onda dropnes stari, kreiranje novog indexa bi trebalo da ti ostavi tabelu sve vreme readonly ali nisam 100% siguran, proveri

Citat:
maroon984:
Da li možeš da mi objesniš koja je razlika između KEY `gtime_uredjaj_idx` (`Uredjaj`, `Gtime`) i (`Gtime`,`Uredjaj`)?


pa key (a,b) moze da se koristi za
- where a=konstanta
- where a=konstanta and b=konstanta
- where a > konstanta
- where a < kosntanta
- whwre a between kosntanta and konstanta

i to je to
dakle ne moze da se koristi za
- where b = konstanta
- where b between / > / <
- where a between/>/< AND b = konstanta

etc etc

to je dakle klasican btree index, ista prica je i sa 3 ili 4 ili 10 clanova .. dakle ako imas (a,b,c,d,e,f)
a = konstanta and b = konstanta and c = kosntanta and d between 1 and 2 -- i sad dalje ne moze e i f jer onog trenutka kada uradis range dalje ne mozes da koristis taj index

isto tako ne vredi ti b = konstanta ako ne koristis a jer on ne zna gde je taj index

nadam se da je jasno, ima to lepse objasnjeno kod nas u dokumentaciji, bese ovde
http://dev.mysql.com/doc/refman/5.6/en/range-optimization.html
[ maroon984 @ 26.02.2015. 14:54 ] @
Bogdane, car si!
Hvala na ovome, pokušaću.

[ maroon984 @ 16.03.2015. 09:02 ] @
Samo da javim da sam promijenio raspored kolona u kompozitnom index-u, i upit koji se izvršavao 60s sada se izvršava za 0.03s. Nevjerovatno!
Bogdane, neizmjerno hvala!