这是我的sql结构:
`errors_log`
-> `id`,
-> `error`,
-> `create_date`;
`logs`
-> `log_id`,
-> `log_label`,
-> `log_date`;
首先有超过10万行,第二行有30 000行。 我的问题是如何在一个按日期排序的SQL问题中获取这些值,尽可能最快。我试过了联盟,但是sql需要花费很多时间才最终崩溃。 简而言之,我希望从日期
中获取此表中的数据答案 0 :(得分:1)
获取100 000(30 000)条记录的速度相当快(假设您在*_date
上有一个索引)。
根据混合表排序数据的速度有多慢(即时分类130 000条记录)。
理想的解决方案可能是将表合并为一个这样的表:
CREATE TYPE logs (
`id` UNSIGNED INT AUTO_INCREMENT,
`label` VARCHAR(255),
`date` DATETIME,
`type` ENUM('normal', 'error'),
PRIMARY KEY (`id),
INDEX (`date`),
INDEX (`type`, `date`)
)
这样你就可以利用非常迅速的MySQL索引。
另一个解决方案是创建如下所示的关系表:
CREATE TABLE log_dates (
`id` UNSIGNED INT AUTO_INCREMENT,
`date` DATETIME,
`log_id` INT NULL, -- points to logs table (column id)
`error_id` INT NULL, -- points to errors table
PRIMARY KEY (`id`),
INDEX (`date`),
UNIQUE KEY (`log_id`),
UNIQUE KEY (`error_id`)
)
记录看起来像:
(NULL, NOW(), $result_from_insert_log, NULL)
(NULL, NOW(), NULL, $result_from_insert_error)
而不是编写病态联接,它会从log_dates
中选择所有记录并将它们与错误/日志配对。 但我不会这样做。
您也可以尝试使用VIEW
s,但根据some stack answers和几篇博文[1],[2],他们不会带来性能提升:
在评论中,我喜欢它们方便的SQL封装的视图 通常必须在SQL语句中重复的逻辑 但在整个申请中。有时候方便 虽然成本很高,特别是当TEMPTABLE算法时 使用
我能想到的最后一件事是某种“聚合”表,它会缓存所有日志,会在后台刷新(比如24小时一次,或者在某些事件之后),这很好,当你穿上不需要最新的结果(使用table locking):
CREATE TABLE `logs_aggregate` (
`id` UNSIGNED INT NOT NULL AUTO_INCREMENT,
`message` VARCHAR(255),
`type` ENUM('normal', 'error') DEFAULT 'normal',
`date` DATETIME,
PRIMARY KEY (`id`),
INDEX (`date`)
);
手动表重组:
-- Prevent data change during the progress
LOCK TABLES logs READ,
errors_log READ,
logs_aggregate WRITE;
-- Empty aggregated data
TRUNCATE TABLE logs_aggregate;
-- Insert errors
INSERT INTO logs_aggregate (id, message, type, date) VALUES (
SELECT NULL, error, 'error', create_date
FROM errors_log
);
-- Insert normal logs
INSERT INTO logs_aggregate (id, message, type, date) VALUES (
SELECT NULL, log_label, 'normal', log_date
FROM logs
);
-- Allow writing again
UNLOCK TABLES;
并确保不使用将所有记录提取到内存中的模型(例如在php构造ToArray()
中),而不是按顺序处理记录。
答案 1 :(得分:0)
所以,SELECT UNION
太慢了,你确实希望数据像一样返回一个联合查询,但是你只想进行一次SQL调用?必须妥协这两个要求中的一个。
ORDER BY date
。由于您的数据已经排序,因此您的合并将在O(n)处运行。