Saya mencoba untuk menyelesaikan masalah berikut selama sekitar satu jam sekarang dan masih belum bisa menyelesaikannya.
Oke, saya punya meja (MyISAM):
+---------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| http | smallint(3) | YES | MUL | 200 | |
| elapsed | float(6,3) | NO | | NULL | |
| cached | tinyint(1) | YES | | NULL | |
| ip | int(11) | NO | | NULL | |
| date | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+---------+-------------+------+-----+-------------------+----------------+
Tolong jangan pedulikan indeksnya, saya telah berusaha mencari solusi. Sekarang, inilah pertanyaan saya.
SELECT http,
COUNT( http ) AS count
FROM reqs
WHERE DATE(date) >= cast(date_sub(date(NOW()),interval 24 hour) as datetime)
GROUP BY http
ORDER BY count;
tabel ini menyimpan informasi tentang permintaan web masuk sehingga basis datanya agak besar.
+-----------+
| count(id) |
+-----------+
| 782412 |
+-----------+
perhatikan bahwa tidak ada cara yang lebih baik untuk mengatur kunci primer karena kolom id akan menjadi satu-satunya pengidentifikasi unik yang saya miliki. Permintaan yang disebutkan di atas membutuhkan waktu sekitar 0,6-1,6 detik untuk dijalankan.
Indeks mana yang pintar? Saya pikir tanggal pengindeksan akan memberi saya kardinalitas "buruk" dan karenanya MySQL tidak akan menggunakannya. http juga merupakan pilihan yang buruk karena hanya ada sekitar 20 nilai yang berbeda.
Terima kasih atas bantuannya!
Pembaruan 1 Saya telah menambahkan indeks pada (http, tanggal) seperti yang disarankan ypercube:
mysql> CREATE INDEX httpDate ON reqs (http, date);
dan menggunakan kueri, tetapi kinerjanya sama buruknya. Indeks yang ditambahkan:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| reqs | 0 | PRIMARY | 1 | id | A | 798869 | NULL | NULL | | BTREE | |
| reqs | 1 | httpDate | 1 | http | A | 19 | NULL | NULL | YES | BTREE | |
| reqs | 1 | httpDate | 2 | date | A | 99858 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
dan MENJELASKAN
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
| 1 | PRIMARY | r | range | NULL | httpDate | 3 | NULL | 20 | Using index for group-by; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | ri | ref | httpDate | httpDate | 3 | func | 41768 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+-----------------------------------------------------------+
Versi server MySQL:
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| protocol_version | 10 |
| version | 5.1.73 |
| version_comment | Source distribution |
| version_compile_machine | x86_64 |
| version_compile_os | redhat-linux-gnu |
+-------------------------+---------------------+
5 rows in set (0.00 sec)
sumber
http
kolom yang dapat dibatalkan. Saya akan menyelidiki besok, jika saya punya waktu.http NOT NULL
) dan menyalin semua data ke dalamnya (kecuali baris dengan http NULL tentu saja.)Jawaban:
Saya punya tiga saran
SARAN # 1: Tulis ulang kueri
Anda harus menulis ulang kueri sebagai berikut
atau
WHERE seharusnya tidak memiliki fungsi di kedua sisi dari tanda sama dengan. Memiliki tanggal di sisi kiri tanda sama dengan membuatnya lebih mudah bagi Pengoptimal Permintaan untuk menggunakan indeks terhadapnya.
SARAN # 2: Indeks Pendukung
Saya juga menyarankan indeks yang berbeda
Saya menyarankan urutan kolom ini karena semua
date
entri akan bersebelahan dalam indeks. Kemudian, kueri hanya mengumpulkanhttp
nilai tanpa melewatkan celahhttp
.SARAN # 3: Penyangga Kunci Lebih Besar (Opsional)
MyISAM hanya menggunakan caching indeks. Karena kueri tidak boleh menyentuh
.MYD
file, Anda harus menggunakan Buffer Kunci MyISAM sedikit lebih besar.Untuk mengaturnya ke 256 juta
Kemudian, atur
my.cnf
Restart MySQL tidak diperlukan
Cobalah !!!
sumber
Ubah tipe kolom tanggal Anda menjadi bilangan bulat. Simpan tanggal sebagai tanggal Unix dalam bilangan bulat. Timestamp Jauh lebih besar dari int. Anda akan mendapatkan beberapa dari itu.
sumber
INT
danTIMESTAMP
membutuhkan 4 byte.