Saya memiliki masalah dengan INDEKS DATETIME (atau bahkan kencan) sebagai bagian pertama dari KUNCI UTAMA saya.
Saya menggunakan MySQL 5.5
Inilah dua meja saya:
-- This is my standard table with dateDim as a dateTime
CREATE TABLE `stats` (
`dateDim` datetime NOT NULL,
`accountDim` mediumint(8) unsigned NOT NULL,
`execCodeDim` smallint(5) unsigned NOT NULL,
`operationTypeDim` tinyint(3) unsigned NOT NULL,
`junkDim` tinyint(3) unsigned NOT NULL,
`ipCountryDim` smallint(5) unsigned NOT NULL,
`count` int(10) unsigned NOT NULL,
`amount` bigint(20) NOT NULL,
PRIMARY KEY (`dateDim`,`accountDim`,`execCodeDim`,`operationTypeDim`,`junkDim`,`ipCountryDim`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-- Here is a copy with datDim as an integer
CREATE TABLE `stats_todays` (
`dateDim` int(11) unsigned NOT NULL,
`accountDim` mediumint(8) unsigned NOT NULL,
`execCodeDim` smallint(5) unsigned NOT NULL,
`operationTypeDim` tinyint(3) unsigned NOT NULL,
`junkDim` tinyint(3) unsigned NOT NULL,
`ipCountryDim` smallint(5) unsigned NOT NULL,
`count` int(10) unsigned NOT NULL,
`amount` bigint(20) NOT NULL,
PRIMARY KEY (`dateDim`,`accountDim`,`execCodeDim`,`operationTypeDim`,`junkDim`,`ipCountryDim`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Saya mengisi kedua tabel dengan data yang persis sama (mendekati 10.000)
Tapi:
- tabel stats menggunakan DATETIME untuk dateDim
- stats_todays gunakan un INTEGER dengan TO_DAYS () untuk dateDim
Pertanyaan saya adalah: mengapa MySQL TIDAK MENGGUNAKAN KUNCI UTAMA ketika bagian pertama dari indeks adalah sebuah datetime ??? Ini sangat aneh karena Dengan data yang sama tetapi dikonsolidasikan dengan INTEGER dan TO_DAYS (dateDim) permintaan yang sama mengguncang ....
Contoh dengan tabel statistik (dan datetime):
SELECT *
FROM `stats`
WHERE
dateDim = '2014-04-03 00:00:00'
AND accountDim = 4
AND execCodeDim = 9
AND operationTypeDim = 1
AND junkDim = 5
AND ipCountryDim = 3
=> 1 result (4.5sec)
Explain:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE stats ALL NULL NULL NULL NULL 8832329 Using where
Permintaan yang sama pada tabel lainnya stats_todays (Dengan INTEGER dan TO_DAYS ())
EXPLAIN SELECT *
FROM `stats_todays`
WHERE
dateDim = TO_DAYS('2014-04-03 00:00:00')
AND accountDim = 4
AND execCodeDim = 9
AND operationTypeDim = 1
AND junkDim = 5
AND ipCountryDim = 3
=> Result 1 row (0.0003 sec)
Explain:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE stats_todays const PRIMARY PRIMARY 13 const,const,const,const,const,const 1
Jika Anda membaca posting lengkap, Anda memahami bahwa itu bukan masalah kardinalitas rendah karena permintaan bekerja dengan kardinalitas yang sama persis dengan bidang INTEGER dateDim ....
Berikut ini beberapa detail lanjutan:
SELECT COUNT( DISTINCT dateDim )
FROM stats_todays
UNION ALL
SELECT COUNT( DISTINCT dateDim )
FROM stats;
Result:
COUNT(DISTINCT dateDim)
2192
2192
Berikut ini adalah deskripsi INDEX:
SHOW INDEXES FROM `stats`
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
stats 0 PRIMARY 1 dateDim A 6921 NULL NULL BTREE
stats 0 PRIMARY 2 accountDim A 883232 NULL NULL BTREE
stats 0 PRIMARY 3 execCodeDim A 8832329 NULL NULL BTREE
stats 0 PRIMARY 4 operationTypeDim A 8832329 NULL NULL BTREE
stats 0 PRIMARY 5 junkDim A 8832329 NULL NULL BTREE
stats 0 PRIMARY 6 ipCountryDim A 8832329 NULL NULL BTREE
SHOW INDEXES FROM `stats_todays`
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
stats_todays 0 PRIMARY 1 dateDim A 7518 NULL NULL BTREE
stats_todays 0 PRIMARY 2 accountDim A 4022582 NULL NULL BTREE
stats_todays 0 PRIMARY 3 execCodeDim A 8045164 NULL NULL BTREE
stats_todays 0 PRIMARY 4 operationTypeDim A 8045164 NULL NULL BTREE
stats_todays 0 PRIMARY 5 junkDim A 8045164 NULL NULL BTREE
stats_todays 0 PRIMARY 6 ipCountryDim A 8045164 NULL NULL BTREE
SELECT dateDim, COUNT (*) DARI statistik GROUP BY dateDim WITH ROLLUP
- memberitahu ada 2192 tanggal yang berbeda, dan partisi ulang itu lancar (sekitar 3000 - 4000 baris berdasarkan tanggal)
- ada 8 831 990 baris dalam tabel
- Sama untuk tabel lainnya
- Saya mencoba dengan COVERING INDEX (mengganti * dengan semua kolom PK) => tidak ada yang berubah
- Saya mencoba paksa | gunakan indeks => tidak ada yang berubah
- Sama dengan bidang tanggal, bukan datetime
- Sama dengan INDEX atau UNIQUE bukan kunci utama
sumber
date
bukandatetime
?WHERE dateDim = DATE('2014-04-03 00:00:00')
?Jawaban:
Ini adalah bug di 5.5.x. Lihat di sini
Itu menunjukkan bahwa permintaan Anda seharusnya
sumber
Karena versi int tabel
berfungsi dengan baik dalam hal permintaan, Anda harus memiliki dateDim berisi UNIX_TIMESTAMP () dari string datetime. Kueri Anda akan terlihat lebih seperti ini:
sumber