在一个非常大的MySQL分析表中-我应该索引时间戳吗?
我希望在我拥有的一个非常大的MySQL分析表上提高查询速度。此表跟踪游戏服务器上的玩家计数,结构如下所示:在一个非常大的MySQL分析表中-我应该索引时间戳吗?,mysql,database,indexing,Mysql,Database,Indexing,我希望在我拥有的一个非常大的MySQL分析表上提高查询速度。此表跟踪游戏服务器上的玩家计数,结构如下所示: `server_tracker` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` int(10) unsigned NOT NULL, `port` smallint(5) unsigned NOT NULL, `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
`server_tracker` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ip` int(10) unsigned NOT NULL,
`port` smallint(5) unsigned NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`players` tinyint(3) unsigned NOT NULL,
`map` varchar(28) NOT NULL,
`portjoin` smallint(5) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_tracking_ip_port` (`ip`,`port`)
) ENGINE=InnoDB AUTO_INCREMENT=310729056 DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED |
此表经常插入到中,每小时跟踪10多次10k+服务器。然而,每小时数据都被取出来并取平均值,然后放入一个结构基本相同的平均表中
目前,我将IP/端口设置作为密钥。然而,有时在进行每小时平均时会有点慢,所以我很好奇是否值得在时间戳上添加一个索引,它通常用于从特定时间段选择数据,如:
SELECT `players`
FROM `server_tracker`
WHERE `ip` = x
AND `port` = x
AND `date` > NOW()
AND `date` < NOW() + INTERVAL 60 MINUTE
ORDER BY `id` DESC
MySQL和脚本中最重要的信息之一是了解MySQL,很少有例外情况,一个查询只能使用一个索引。 因此,当where子句中使用全部4个时,设置一个列并不需要太多依赖于索引 这些字段上只有一个组合索引柄。 字段的顺序非常重要,因为此索引也可用于其他查询 例如:
MariaDB [(none)]> use tmp
Database changed
MariaDB [tmp]> SET PROFILING=ON;
Query OK, 0 rows affected (0.00 sec)
MariaDB [tmp]>
MariaDB [tmp]> SELECT * FROM content;
+----+------+---------------------+--------+------+--------------+------+------+------+------+
| id | Wert | Zeitstempel | WertID | aaa | d | e | wwww | n | ddd |
+----+------+---------------------+--------+------+--------------+------+------+------+------+
| 1 | 10 | 2001-01-01 00:00:00 | 1 | NULL | 1.5000 | NULL | NULL | 1 | NULL |
| 2 | 12.3 | 2001-01-01 00:01:00 | 2 | NULL | 2.5000 | NULL | NULL | 2 | NULL |
| 3 | 17.4 | 2001-01-01 00:02:00 | 3 | NULL | 123456.1250 | NULL | NULL | 3 | NULL |
| 4 | 10.9 | 2001-01-01 01:01:00 | 1 | NULL | 1000000.0000 | NULL | NULL | 4 | NULL |
| 5 | 15.4 | 2001-01-01 01:02:00 | 2 | NULL | NULL | NULL | NULL | 5 | NULL |
| 6 | 20.9 | 2001-01-01 01:03:00 | 3 | NULL | NULL | NULL | NULL | 6 | NULL |
| 7 | 22 | 2001-01-02 00:00:00 | 1 | NULL | NULL | NULL | NULL | 7 | NULL |
| 8 | 12.3 | 2001-01-02 00:01:00 | 2 | NULL | NULL | NULL | NULL | 8 | NULL |
| 9 | 17.4 | 2001-01-02 00:02:00 | 3 | NULL | NULL | NULL | NULL |
+----+------+---------------------+--------+------+--------------+------+------+------+------+
13 rows in set (0.00 sec)
MariaDB [tmp]>
MariaDB [tmp]> SHOW PROFILE;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000031 |
| checking permissions | 0.000005 |
| Opening tables | 0.000036 |
| After opening tables | 0.000004 |
| System lock | 0.000003 |
| Table lock | 0.000002 |
| After opening tables | 0.000005 |
| init | 0.000013 |
| optimizing | 0.000006 |
| statistics | 0.000013 |
| preparing | 0.000010 |
| executing | 0.000002 |
| Sending data | 0.000073 |
| end | 0.000003 |
| query end | 0.000003 |
| closing tables | 0.000006 |
| freeing items | 0.000003 |
| updating status | 0.000012 |
| cleaning up | 0.000003 |
+----------------------+----------+
19 rows in set (0.00 sec)
MariaDB [tmp]>
当有WHERE field1或field1和field2或field1、field2和field3时,将使用field1、field2和field3上的索引。如果您在WHERE字段2或used字段3或FIELD2 and字段中,则不使用此索引。3因此始终使用第一个字段
很容易发现你是否喜欢这个查询,你可以直接运行你的查询,EXPALIN和beommst,直接知道是否使用了索引以及使用了哪个索引。如果有几行可以作为指示符,则单独的值在穆利利齐耶伦一行的下面。这个数字越小,执行查询的效果越好
MariaDB [tmp]> EXPLAIN select * from content;
+------+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | content | ALL | NULL | NULL | NULL | NULL | 13 | |
+------+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
MariaDB [tmp]>
Anternativ您可以查看探查器查询在什么容量下需要多长时间以及关于优化服务器的信息
例如:
MariaDB [(none)]> use tmp
Database changed
MariaDB [tmp]> SET PROFILING=ON;
Query OK, 0 rows affected (0.00 sec)
MariaDB [tmp]>
MariaDB [tmp]> SELECT * FROM content;
+----+------+---------------------+--------+------+--------------+------+------+------+------+
| id | Wert | Zeitstempel | WertID | aaa | d | e | wwww | n | ddd |
+----+------+---------------------+--------+------+--------------+------+------+------+------+
| 1 | 10 | 2001-01-01 00:00:00 | 1 | NULL | 1.5000 | NULL | NULL | 1 | NULL |
| 2 | 12.3 | 2001-01-01 00:01:00 | 2 | NULL | 2.5000 | NULL | NULL | 2 | NULL |
| 3 | 17.4 | 2001-01-01 00:02:00 | 3 | NULL | 123456.1250 | NULL | NULL | 3 | NULL |
| 4 | 10.9 | 2001-01-01 01:01:00 | 1 | NULL | 1000000.0000 | NULL | NULL | 4 | NULL |
| 5 | 15.4 | 2001-01-01 01:02:00 | 2 | NULL | NULL | NULL | NULL | 5 | NULL |
| 6 | 20.9 | 2001-01-01 01:03:00 | 3 | NULL | NULL | NULL | NULL | 6 | NULL |
| 7 | 22 | 2001-01-02 00:00:00 | 1 | NULL | NULL | NULL | NULL | 7 | NULL |
| 8 | 12.3 | 2001-01-02 00:01:00 | 2 | NULL | NULL | NULL | NULL | 8 | NULL |
| 9 | 17.4 | 2001-01-02 00:02:00 | 3 | NULL | NULL | NULL | NULL |
+----+------+---------------------+--------+------+--------------+------+------+------+------+
13 rows in set (0.00 sec)
MariaDB [tmp]>
MariaDB [tmp]> SHOW PROFILE;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000031 |
| checking permissions | 0.000005 |
| Opening tables | 0.000036 |
| After opening tables | 0.000004 |
| System lock | 0.000003 |
| Table lock | 0.000002 |
| After opening tables | 0.000005 |
| init | 0.000013 |
| optimizing | 0.000006 |
| statistics | 0.000013 |
| preparing | 0.000010 |
| executing | 0.000002 |
| Sending data | 0.000073 |
| end | 0.000003 |
| query end | 0.000003 |
| closing tables | 0.000006 |
| freeing items | 0.000003 |
| updating status | 0.000012 |
| cleaning up | 0.000003 |
+----------------------+----------+
19 rows in set (0.00 sec)
MariaDB [tmp]>
是的,您可能需要在WHERE子句中使用的任何内容上建立索引。了解所有查询的访问路径非常重要,因为这些查询是试图创建索引的瓶颈—单列索引、复合索引和覆盖索引。否则,我们只能给出粗略的回答。如果走错了路,会让你变得更糟off@ceejayoz我的问题是,这会显著增加磁盘空间使用率吗?难道它不需要将所有这些日期都保存在一个文件中,以便将数百万行超时增长吗?我不太清楚索引在内部是如何工作的,因为大多数解释只解释了为什么以及如何使用它们。@Drew你所说的访问路径是什么意思?如中所示,我将在此表上运行的查询类型是什么?我正在运行的唯一查询类型是OP中的select查询。通过查找IP/端口/日期来选择playercount。此数据从未更新或更改-但它确实会经常被删除。正确。你的情况是好的,因为没有鹅追逐,看看还有什么问题。。。索引更改会影响。我在OP中添加了一些新信息。您说过每个查询只能使用1个索引吗?我把IP/端口设置作为一个键,除了日期之外,WHERE子句也使用这个键。没有其他类型的查询真正在这个表上运行。如果您只能使用1个索引,那么索引日期是否有用?对不起,如果我误解了你的帖子,你的英语有点难读。对不起,我已经用谷歌翻译了:-。使用查询中使用的所有字段创建一个索引ALTER TABLE server\u tracker ADD index somename ip、端口、日期;那么查询可以完美地使用它。ALTER表中字段的顺序也很重要。最能降低结果的地方必须是第一位。a示例:10k行,端口a为5000,端口b为5000,ip为1为100。然后ip是索引中的第一个字段。因此,您可以将内部结果集vom 10k总计减少到第一行之后的100行,其中ip=xx,下一个reduce只需搜索100行