假设我们有一个包含当前信息的表“月”和包含历史信息的表“年”的模式。每个表有大约 65,000 行。
这个模式存在于几个地方,比如地方 A、B 和 C。
要求从每个模式中获取有序信息。没有可能的“物化视图”
据我说,我需要统一所有结果(没有限制):
CREATE VIEW all_results AS
SELECT * FROM A.month
UNION ALL
SELECT * FROM A.year
UNION ALL
SELECT * FROM B.month
....
...然后应用 ORDER BY、COUNT 和 LIMIT
SELECT * FROM all_results ORDER BY column1 LIMIT 0,23
SELECT count(*) FROM all_results
但是这种方法需要将近 20 秒(这对于 Web 解决方案来说太多了)。
有一个更好的方法吗?
(从 dup 问题添加)此变体也需要 20 秒。
SELECT SQL_CALC_FOUND_ROWS * FROM(
SELECT * FROM A.month
UNION ALL
SELECT * FROM A.year
UNION ALL
SELECT * FROM B.month
....
) AS united
LIMIT 0,23
并计算总数:SELECT FOUND_ROWS()
重新考虑获取总数的必要性;这可能是最昂贵的部分。
分别对这两个查询中的每一个进行计时。分别优化它们。然后重新计时。
您真的需要所有 (
*
) 列吗?TEXT
和BLOB
列提取额外的费用。拥有
VIEW
;没有任何优势 相反,有一个很大的缺点是UNION
会运行两次!(在 MySQL 8.0 中,WITH
可能会避免这种“两次”。)对于带有 的查询
LIMIT
,您可以并且应该对每个子查询进行限制。更多细节在这里。每张桌子都需要
INDEX(column1)
。这应该会显着加快(超过 2 倍)大计数:
这是因为
COUNT(*)
比将所有行收集到临时表中或计算该表中的行数要快。我预测我所有建议的结果将在 5 秒内得到它。如果没有,请提供
SHOW CREATE TABLE
每张桌子。以及您使用的 MySQL 版本。通过 10K 行分页?
让我们从另一边解决你的问题。如果我计算正确,您的输出中大约有 10,000 页?如果老了,什么用户可以在死前翻阅那么多页面?
如果您有几十个页面,那么为了用户的理智,想出另一种方式向他们显示数据。分页不实用。
让我举一个简单的例子——对世界上所有城市的所有列表进行分页...
计划A,比如分页……首先让用户选择哪个国家。(即使这样也很笨拙,因为大约有 250 个国家/地区。)然后选择一个省/州/州/等。然后选择 A..Z,然后翻阅城市。
计划 B,移到更远的地方... 提供一些“搜索”机制——用于按名称的一部分、国家/州/省/等、人口范围、世界的一部分等进行搜索。