it-swarm-tr.com

Birisi MySQL'de DATETIME alanının tarih kısmında nasıl bir endeks oluşturur?

DATETIME alanının tarih kısmında bir dizini nasıl oluşturabilirim?

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, bir işlemin tarihini ve saatini olduğu gibi kaydetmek için kullanılır

Masamda 1.000.000'in üzerinde kayıt var ve ifade 

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

uzun zaman alır.

DÜZENLE: 

Bu blog gönderisine " Neden MySQL’in DATETIME’sinin kullanılabileceğine ve kullanılmaması gerektiğine" bakın

61
Charles Faiga

Doğru hatırlıyorsam, bu bir tablodan geçirilir çünkü sütunu bir işlevden geçirirsiniz. MySQL, her sütun için işlevi itaatkar bir şekilde çalıştırır, sorgu en iyi duruma getiricisi işlevin gerçekten sonuçlarını bilemediğinden dizini atlayarak.

Yapacağım şey şunun gibi bir şey:

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

Bu size 2008-08-17 tarihinde gerçekleşen her şeyi vermeli.

56
Michael Johnson

Kulağa hoş gelmek istemem ama basit bir yol, bunun üzerine sadece tarih ve dizini içeren yeni bir sütun eklemek olacaktır.

9
Mike Tunnicliffe

Sadece tarih kısmında bir dizin oluşturamazsınız. Yapman gereken bir sebep var mı?

Sadece tarih kısmında bir endeks oluşturabilseniz bile, optimiser muhtemelen yukarıdaki sorgu için kullanmayacaktır.

Sanırım onu ​​bulacaksın 

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

Verimlidir ve ne istiyorsan onu yapar.

8
MarkR

Başka bir seçenek ( sürüm 5.7.3 ve üstü ile ilgili), tarih/saat sütununu temel alarak oluşturulmuş/sanal bir sütun oluşturmak, ardından dizine eklemektir.

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

MySql'in özelliklerini bilmiyorum ama tarih alanını tamamen dizine eklemenin zararı nedir?

O zaman sadece ara:

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

Dizinler b-ağaçları veya makul başka bir şeyse, bunlar çabucak bulunmalıdır.

3
Clinton Pierce

Valeriy Kravchuk bir özellik isteği üzerine bu konuda MySQL sitesinde bu sorunun kullanılacağını söyledi.

"Bu arada, DATETIME değerlerini dizeler olarak depolamak için karakter sütunları kullanabilir, yalnızca ilk N karakteri dizine eklenebilir. MySQL 5'teki tetikleyicilerin dikkatli bir şekilde kullanılmasıyla, bu fikri temel alan oldukça sağlam bir çözüm oluşturabilirsiniz."

Bu sütunu eklemek oldukça kolay bir yordam yazabilir ve ardından tetikleyicilerle bu sütunu senkronize halde tutabilirsiniz. Bu dize sütunundaki dizin oldukça hızlı olmalıdır.

2
Ray Jenkins

Oldukça iyi çalışmanın iyi ve iyi bir çözümü datetime yerine zaman damgasını kullanmaktır . INT olarak depolanır ve yeterince iyi indekslenir .. milyon rekor ve yavaşladı, nihayet bunun kötü endeksli alandan (datetime) kaynaklandığına işaret ettim.

2
Valentin Rusk

datetime LIKE% 'si de dizini yakalayamaz.

Bunu kullanın: WHERE datetime_field> = curdate ();
Dizini yakalayacaktır, 
ve kapak bugün: 00: 00: 00 şu ana kadar: 23: 59: 59
Bitti.

1
Dr. Tyrell

MySQL'in özelliklerini bilmiyorum ama tarih alanını tamamen dizine eklemenin zararı nedir?

* Ağaçlar için işlevsel büyü kullanıyorsanız, kareler, ... gitmiş demektir, çünkü değerleri elde etmek için işlevi çağırmalısınız. Ancak, ilerideki sonuçları bilmediğiniz için, tablonun tam taramasını yapmanız gerekir.

Eklenecek bir şey yok.

Belki bilgisayarlı (hesaplanmış?) Dizinler gibi bir şey demek istiyorsun ... ama bugüne kadar, bunu Intersystems Caché'de gördüm. İlişkisel veritabanlarında bir durum olduğunu sanmıyorum (AFAIK).

Bana göre iyi bir çözüm, şu şekildedir (güncellenmiş clintp örneği):

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

Bana göre 00:00:00.0000 veya 00:00 kullanmanız farketmez (Genel olarak bu formatta kullandım).

1
antonia007

'Açıkla' ne diyor? (EXPLAIN SELECT komutunu çalıştırın * FROM işlem listesinden date (TranDateTime) = '2008-08-17')

Dizininizi date () işlevi nedeniyle kullanmıyorsa, bir aralık sorgusu hızlı çalışmalıdır:

SELECT * işlem listesinden TranDateTime> = '2008-08-17' VE TranDateTime <'2008-08-18'

0
nathan

Bir işleve dayalı bir dizin yapmak yerine (eğer mysql'de mümkün ise), cümlecikinizin bir aralık karşılaştırması yapmasını sağlayın. Gibi bir şey:

Nerede TranDateTime> '2008-08-17 00:00:00 've TranDateTime < '2008-08-17 11:59:59')

Bu, DB'nin seçimi yapmak için TranDateTime üzerindeki dizini kullanmasına izin verir (bir tane var mı?)?.

0
Justsalt

Tabloyu değiştirmek bir seçenekse veya yeni bir tane yazıyorsanız, tarih ve saati ilgili türlerle ayrı sütunlara kaydetmeyi düşünün. Daha küçük bir anahtar alana ve düşük depolama alanına sahip bir performans elde edersiniz (bir tarih zamanından türetilen yalnızca bir tarih sütunu ile karşılaştırıldığında). Bu aynı zamanda bileşik anahtarlarda, diğer sütunlardan önce bile kullanılmasını mümkün kılar.

OP’nin durumunda:

+-------------------+------------------+------+-----+---------+----------------+
| 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