1

我有一个包含来自游戏服务器的日志的表。这些日志以一种非常糟糕的方式保存(imo),但我需要设法收集它们。该表当前包含 4,000,000 行并且还在增长(这是 4 或 5 个月的日志)。

现在我正在寻找一种方法来过滤 SELECT 查询而不会给数据库带来太多负载。这是表结构:

CREATE TABLE `rp_logs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `time` int(11) NOT NULL,
  `type` enum('joinleave','kill','chat','spawn','ac','cmd','misc','hidden','cp','admin') NOT NULL,
  `msg` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

现在我可以过滤时间范围和日志类型。但我想要更多。日志消息大部分时间都包含玩家 ID。如果我能添加一个msg LIKE '%playerid%'. 但是,如果我只是用一个简单的查询来做到这一点,它会将搜索操作延长到 +30 秒。

目前我只是这样做(这不是 100% 的代码,只是我所做的方法):

SELECT * FROM rp_logs 
WHERE time > $start AND time < $end 
AND (type = 'kill' or type = 'cmd' or ... );

有没有更好的方法来优化查询,所以它不那么重。

我所知道的可能是对时间进行查询,然后使用 msg 上的过滤器对其进行子查询,但我不知道它是如何工作的。我似乎无法让它工作。

这是 30 行示例数据:

INSERT INTO `rp_logs` (`id`, `time`, `type`, `msg`) VALUES
(4314121, 1366788849, 'chat', '[OOC] Danny Doss (STEAM_0:0:20730895): He logged a long time ago Itt'),
(4314122, 1366788849, 'chat', 'Eric Crendor (STEAM_0:0:46944468): the *'),
(4314123, 1366788851, 'spawn', 'Danny Doss (STEAM_0:0:20730895) created entity prop_physics with model models/props_building_details/storefront_template001a_bars.mdl'),
(4314124, 1366788855, 'chat', '[OOC] Eric Crendor (STEAM_0:0:46944468): did he?'),
(4314125, 1366788868, 'chat', '[OOC] Danny Doss (STEAM_0:0:20730895): 5 minutes ago'),
(4314126, 1366788872, 'misc', 'Daedalus Richmond (STEAM_0:1:20442870) has been made a Arms Dealer'),
(4314127, 1366788879, 'chat', '[OOC] Eric Crendor (STEAM_0:0:46944468): nontheless we killed him then started cracking, he still left whilst raid?'),
(4314128, 1366788893, 'chat', '[OOC] Jasonafex Mittsies (STEAM_0:0:29686591): He left because he went to bed'),
(4314129, 1366788899, 'chat', '[OOC] Danny Doss (STEAM_0:0:20730895): Can''t do anything about it'),
(4314130, 1366788903, 'chat', 'Eric Crendor (STEAM_0:0:46944468): left go to next dealer'),
(4314131, 1366788904, 'chat', '[OOC] Danny Doss (STEAM_0:0:20730895): It is not warnable'),
(4314132, 1366788909, 'chat', 'Eric Crendor (STEAM_0:0:46944468): * my grAMMAR'),
(4314133, 1366788912, 'chat', 'Eric Crendor (STEAM_0:0:46944468): damn keyboard'),
(4314134, 1366788913, 'spawn', 'Danny Doss (STEAM_0:0:20730895) created entity prop_physics with model models/props_c17/furnituredrawer001a.mdl'),
(4314135, 1366788919, 'spawn', 'Danny Doss (STEAM_0:0:20730895) created entity prop_physics with model models/props_combine/combine_window001.mdl'),
(4314136, 1366788921, 'chat', 'Eric Crendor (STEAM_0:0:46944468): k'),
(4314137, 1366788923, 'spawn', 'Danny Doss (STEAM_0:0:20730895) created entity prop_physics with model models/props_c17/furniturecouch002a.mdl'),
(4314138, 1366788932, 'kill', 'Danny Doss (STEAM_0:0:20730895) was killed by Entity [0][worldspawn], weapon: N/A'),
(4314139, 1366788947, 'spawn', 'Jasonafex Mittsies (STEAM_0:0:29686591) created entity prop_physics with model models/props_lab/blastdoor001c.mdl'),
(4314140, 1366788960, 'misc', 'AceFTFW (STEAM_0:0:37117785) has been made a Citizen'),
(4314141, 1366788960, 'joinleave', 'Ace Jones (STEAM_0:0:37117785) joined the game.'),
(4314142, 1366788967, 'joinleave', 'Jasonafex Mittsies (STEAM_0:0:29686591) has left the game.'),
(4314143, 1366788971, 'joinleave', 'Danny Doss (STEAM_0:0:20730895) has left the game.'),
(4314144, 1366788981, 'misc', 'Ace Jones (STEAM_0:0:37117785) has been made a Arms Dealer'),
(4314145, 1366788989, 'chat', 'Eric Crendor (STEAM_0:0:46944468): okay'),
(4314146, 1366788996, 'chat', 'Eric Crendor (STEAM_0:0:46944468): Ace'),
(4314147, 1366789011, 'chat', 'Eric Crendor (STEAM_0:0:46944468): wheres your sho'),
(4314148, 1366789014, 'chat', 'Eric Crendor (STEAM_0:0:46944468): we wanna get some guns'),
(4314149, 1366789018, 'chat', 'Eric Crendor (STEAM_0:0:46944468): ah k'),
(4314150, 1366789035, 'chat', 'Eric Crendor (STEAM_0:0:46944468): no literally');
4

3 回答 3

2

time在您的字段上添加重复索引。只要您查询相对较窄的时间范围,现有查询的性能提升应该是显着的。

于 2013-04-24T08:00:20.610 回答
1

向包含用户名的数据库添加一个新字段。做“LIKE”,尤其是使用通配符,总是会占用大量资源(因此也需要时间)。此外,如果您有一个单独的用户名字段,您可以在其上放置一个索引,并使其更快。

于 2013-04-24T07:47:28.933 回答
1

LIKE 查询可以替换为 FULLTEXT 搜索。

SELECT * 
FROM rp_logs 
WHERE MATCH (msg) AGAINST ('playerid');

您必须首先将您msg的列声明为 FULLTEXT

ALTER TABLE rp_logs ADD FULLTEXT(msg);

或者

CREATE TABLE `rp_logs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `time` int(11) NOT NULL,
  `type` enum('joinleave','kill','chat','spawn','ac','cmd','misc','hidden','cp','admin') NOT NULL,
  `msg` text NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT (msg)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

进一步阅读:

于 2013-04-24T07:51:28.397 回答