it-swarm-eu.dev

Jak lze vytvořit index v datové části pole DATETIME v MySql

Jak vytvořím index v datové části pole DATETIME?

mysql> SHOW COLUMNS FROM transactionlist;
+-------------------+------------------+------+-----+---------+----------------+
| Field             | Type             | Null | Key | Default | Extra          |
+-------------------+------------------+------+-----+---------+----------------+
| TransactionNumber | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| WagerId           | int(11)          | YES  | MUL | 0       |                |
| TranNum           | int(11)          | YES  | MUL | 0       |                |
| TranDateTime      | datetime         | NO   |     | NULL    |                |
| Amount            | double           | YES  |     | 0       |                |
| Action            | smallint(6)      | YES  |     | 0       |                |
| Uid               | int(11)          | YES  |     | 1       |                |
| AuthId            | int(11)          | YES  |     | 1       |                |
+-------------------+------------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)

TranDateTime se používá k uložení data a času transakce, jak se stane

Můj stůl obsahuje přes 1 000 000 záznamů a prohlášení 

SELECT * FROM transactionlist where date(TranDateTime) = '2008-08-17' 

trvá dlouho.

UPRAVIT: 

Podívejte se na tento příspěvek na blogu " Proč se lze vyhnout MySQL DATETIME "

61
Charles Faiga

Pokud si vzpomínám správně, spustí se celá tabulka, protože prochází sloupec funkcí. MySQL poslušně spustí funkci pro každý sloupec, obchází index, protože optimalizátor dotazů nemůže skutečně znát výsledky funkce.

Co bych udělal, je něco jako:

SELECT * FROM transactionlist 
WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-17 23:59:59.999999';

To by vám mělo dát vše, co se stalo na 2008-08-17.

56
Michael Johnson

Nechci znít roztomilý, ale jednoduchým způsobem by bylo přidat nový sloupec, který by obsahoval pouze datovou část a index.

9
Mike Tunnicliffe

Nelze vytvořit index pouze v datové části. Existuje důvod, proč musíte?

I když byste mohli vytvořit index pouze v datové části, optimalizátor by jej pravděpodobně pro výše uvedený dotaz stále nepoužíval.

Myslím, že to zjistíte 

SELECT * FROM transactionlist WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-18'

Je efektivní a dělá to, co chcete.

8
MarkR

Další možností ( relevantní pro verzi 5.7.3 a výše ) je vytvořit generovaný/virtuální sloupec založený na datetime sloupci, pak jej indexovat.

CREATE TABLE `table` (
`my_datetime` datetime NOT NULL,
`my_date` varchar(12) GENERATED ALWAYS AS (DATE(`my_daetime`)) STORED,
KEY `my_idx` (`my_date`)
) ENGINE=InnoDB;
6
Liran Brimer

Nevím o specifikách mySql, ale co je to škoda jen v indexování datového pole v jeho celistvosti?

Potom stačí vyhledat:

 select * from translist 
     where TranDateTime > '2008-08-16 23:59:59'
        and TranDateTime < '2008-08-18 00:00:00'

Pokud jsou indexy b-stromy nebo něco jiného, ​​co je rozumné, měly by být rychle nalezeny.

3
Clinton Pierce

Valeriy Kravchuk na žádost o funkci pro tento problém na webu MySQL řekl, že tuto metodu použije.

"Mezitím můžete použít sloupce znaků pro ukládání hodnot DATETIME jako řetězců, přičemž pouze první znaky N jsou indexovány. Při pečlivém používání spouštěčů v MySQL 5 můžete vytvořit rozumně robustní řešení založené na této myšlence."

Dalo by se napsat rutinu docela snadno přidat tento sloupec, a pak se spouští udržet tento sloupec synchronizován. Index na tomto sloupci řetězce by měl být velmi rychlý.

2
Ray Jenkins

Jedním a dobrým řešením, které je vcelku dobré, je použít časovou známku jako čas, spíše než datetime. Je uložen jako INT a je dostatečně indexován. , který má asi milion záznamů a zpomalil, nakonec jsem poukázal na to, že to bylo způsobeno špatným indexovaným polem (datetime). Nyní běží velmi rychle.

2
Valentin Rusk

datetime LIKE něco, co% nezachytí ani index.

Použijte toto: WHERE datetime_field> = curdate ();
, Které zachytí index, 
a pokrývají dnes: 00: 00: 00 až do dneška: 23: 59: 59
Hotovo.

1
Dr. Tyrell

Nevím o specifikách mySQL, ale co je to škoda jen v indexování datového pole v jeho celistvosti?

Pokud používáte kouzlo pro * stromy, hash, ... je pryč, protože pro získání hodnot musíte funkci zavolat. Ale protože výsledky před sebou neznáte, musíte provést úplné prohlédnutí tabulky.

Není co dodat.

Možná máte na mysli něco jako počítané (vypočtené?) Indexy ... ale doposud jsem to viděl jen v Intersystems Caché. Nemyslím si, že existuje případ v relačních databázích (AFAIK).

Dobré řešení je podle mého názoru následující (aktualizovaný příklad):

SELECT * FROM translist 
WHERE TranDateTime >= '2008-08-17 00:00:00.0000'
  AND TranDateTime < '2008-08-18 00:00:00.0000'

Ať už používáte 00:00:00.0000 nebo 00:00 podle mého názoru, není rozdíl (obecně jsem ho používal v tomto formátu).

1
antonia007

Co říká 'vysvětlit'? (spusťte transakční seznam EXPLAIN SELECT * FROM, kde datum (TranDateTime) = '2008-08-17')

Pokud nepoužíváte index kvůli funkci date (), dotaz rozsahu by měl běžet rychle:

SELECT * FROM transakční seznam, kde TranDateTime> = '2008-08-17' A TranDateTime <'2008-08-18'

0
nathan

Spíše než dělat index založený na funkci (jestliže to je dokonce možné v mysql) dělat vaše kde klauzule dělat rozsah srovnání. Něco jako:

Kde TranDateTime> '2008-08-17 00:00:00' a TranDateTime < '2008-08-17 11:59:59')

To umožňuje DB použít index na TranDateTime (tam je jeden, vpravo?) Udělat výběr.

0
Justsalt

Pokud je změna tabulky možností nebo píšete novou, zvažte uložení data a času v samostatných sloupcích s příslušnými typy. Získáte výkon tím, že máte mnohem menší prostor pro klíče a omezené úložiště (ve srovnání s datovým sloupcem odvozeným pouze od data). To také umožňuje použití ve složených klíčích, dokonce i před jinými sloupci.

V případě OP:

+-------------------+------------------+------+-----+---------+----------------+
| Field             | Type             | Null | Key | Default | Extra          |
+-------------------+------------------+------+-----+---------+----------------+
| TransactionNumber | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| WagerId           | int(11)          | YES  | MUL | 0       |                |
| TranNum           | int(11)          | YES  | MUL | 0       |                |
| TranDate          | date             | NO   |     | NULL    |                |
| TranTime          | time             | NO   |     | NULL    |                |
| Amount            | double           | YES  |     | 0       |                |
| Action            | smallint(6)      | YES  |     | 0       |                |
| Uid               | int(11)          | YES  |     | 1       |                |
| AuthId            | int(11)          | YES  |     | 1       |                |
+-------------------+------------------+------+-----+---------+----------------+
0
Walf