表名为'log',目前它有5000万行:
id
我有以下查询,以获取每个'domainIP'使用SELECT
`log`.`id`,
`log`.`domainIP`,
COUNT(`log`.`domainIP`) AS "Times",
totalsTable.Totals,
(COUNT(`log`.`domainIP`)/totalsTable.Totals)*100 AS "Percentage"
FROM `log`
JOIN
(
SELECT
`id`,
COUNT(`domainIP`) AS Totals
FROM `log` GROUP BY `id`
) AS totalsTable
ON (`log`.`id` = totalsTable.`id`)
GROUP BY `log`.`domainIP` ORDER BY `log`.`id` ASC, "Percentage" DESC
的次数,以及每个'%pck}的百分比:
| id | domainIP | Times | Totals | Percentage
| foo | 158.132.34.5 | 1 | 1 | 100
| bob | 128.12.244.3 | 2 | 4 | 50
| bob | 19.152.134.4 | 1 | 4 | 25
| bob | 168.152.34.9 | 1 | 4 | 25
| alice | 178.132.64.10 | 1 | 2 | 50
| alice | 188.152.214.200 | 1 | 2 | 50
| peter | 208.162.36.153 | 3 | 4 | 75
| peter | 198.168.94.201 | 1 | 4 | 25
它返回:
CREATE TABLE `log` (
`id` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL,
`eDate` datetime DEFAULT NULL,
`domainIP` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL,
`event` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `log`
ADD UNIQUE KEY `logUnique` (`id`,`eDate`,`event`),
ADD KEY `eDate` (`eDate`),
ADD KEY `id` (`id`,`eDate`),
ADD KEY `event` (`id`,`eDate`,`event`);
结果正是我所需要的,但它无法使用缓慢(需要几分钟)。
这是从phpmyadmin导出的表结构。
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 100 | Using where; Using temporary; Using filesort
1 | PRIMARY | log | ref | logUnique,id,event | logUnique | 453 | totalsTable.id | 1 |
2 | DERIVED | log | index | NULL | id | 459 | NULL | 100 |
对表格的较小版本的EXPLAIN查询结果:
if (Directory.Exists(rootFolder))
{
try
{
string[] valid = { "Test", "OtherTest" };
foreach (string f in Directory.GetFiles(rootFolder))
{
if (valid.Any(v => f.ToString().Contains(v)))
{
// create file
}
}
}
catch
{
// log stuff
}
}
}
我需要制定一个返回相同但可用的查询(以秒为单位返回结果,而不是分钟),但不知道如何
注意:向domainIP添加索引只会略微改善小型样本的响应,但是整个表仍需要10分钟以上才能返回结果。
该表是为其他目的而创建的,如果有的话,我更愿意修改它的结构。
答案 0 :(得分:2)
你可能会发现这有点快。从这个版本开始:
SELECT l.id, l.domainIP, COUNT(*) as Times,
(SELECT COUNT(*) FROM log l2 WHERE l2.id = l.id) as Total
FROM log l
GROUP BY l.id, l.domainIP
ORDER BY l.id ASC;
以id
开头的现有索引应该足够了。
实际上,您甚至可以删除相关子查询来衡量GROUP BY
的性能。如果它不够好,那么你基本上知道你无法改进更复杂的查询。您将需要尝试其他方法,例如使用触发器来维持总计数。
答案 1 :(得分:1)
简要地说,查询花费如此巨大的时间并不奇怪,因为varchar
非唯一 id 和varchar
< EM> DOMAINIP 。字符串比较可能比在许多数量级上比较int
字段要慢。你应该考虑进行非规范化:
longint
; user_names
和id
的{{1}}表格。然后你应该声明表格&#39; user_ips&#39;由user_name
,id
(实际上是来自user_id
的ID)和user_names
组成。只有这几项更改必须显着提高查询速度。希望这会对你有所帮助