MySQL (MariaDB) 从 PHP 调用的查询中执行超时
MySQL (MariaDB) execution timeout within query called from PHP
我正在针对地理定位搜索系统对我的数据库进行压力测试。它已经在这样一个方框 long/lat 索引系统中内置了很多优化,可以在执行弧距计算之前缩小搜索范围。我的目标是从一个 table 服务 10,000,000 名用户。
目前,根据年龄、性别等其他条件,我的查询时间在 0.1 到 0.01 秒之间。这是针对均匀分布在英国的 10,000,000 名用户。
我有一个 LIMIT 条件,因为我需要向用户显示 X 个人,其中 X 可以在 16 到 40 之间。
问题是当没有其他用户/少数用户匹配时,查询可能需要很长时间,因为它无法快速达到 LIMIT,并且可能必须扫描 400,000 行。
可能还有其他优化技术可供我参考,但我的问题是:
有没有办法让查询在 X 秒后放弃?如果花费的时间超过 1 秒,则不会得到 return 结果,我很高兴出现这种情况。在伪查询代码中,它将类似于:
SELECT 数据来自 table WHERE ...... 1 秒后限制 16 放弃
我考虑过一个 cron 解决方案来终止缓慢的查询,但这不是很优雅。在生产环境中,查询将每隔几秒调用一次,因此 cron 需要持续运行。
有什么建议吗?
- 版本为 10.1.14-MariaDB
使用 10.1 版中的 MariaDB,您可以通过两种方式来限制查询。它可以基于时间或查询的行总数来完成。
按行:
SELECT ... LIMIT ROWS EXAMINED rows_limit;
您可以使用关键字 EXAMINED
并设置行数,如您提到的 400000 (自 MariaDB 10.0 起)。
按时间:
If the max_statement_time variable is set, any query (excluding stored
procedures) taking longer than the value of max_statement_time
(specified in seconds) to execute will be aborted. This can be set
globally, by session, as well as per user and per query.
如果你想要它用于特定的查询,就像我想象的那样,你可以使用这个:
SET STATEMENT max_statement_time=1 FOR
SELECT field1 FROM table_name ORDER BY field1;
请记住 max_statement_time
是以秒为单位设置的(与 MySQL 相反,后者是毫秒),因此您可以更改它直到找到最适合您的情况 (自 MariaDB 10.1 起)。
如果您需要更多信息,我推荐您 excellent post 关于查询超时的内容。
希望对您有所帮助。
我正在针对地理定位搜索系统对我的数据库进行压力测试。它已经在这样一个方框 long/lat 索引系统中内置了很多优化,可以在执行弧距计算之前缩小搜索范围。我的目标是从一个 table 服务 10,000,000 名用户。
目前,根据年龄、性别等其他条件,我的查询时间在 0.1 到 0.01 秒之间。这是针对均匀分布在英国的 10,000,000 名用户。
我有一个 LIMIT 条件,因为我需要向用户显示 X 个人,其中 X 可以在 16 到 40 之间。
问题是当没有其他用户/少数用户匹配时,查询可能需要很长时间,因为它无法快速达到 LIMIT,并且可能必须扫描 400,000 行。
可能还有其他优化技术可供我参考,但我的问题是:
有没有办法让查询在 X 秒后放弃?如果花费的时间超过 1 秒,则不会得到 return 结果,我很高兴出现这种情况。在伪查询代码中,它将类似于:
SELECT 数据来自 table WHERE ...... 1 秒后限制 16 放弃
我考虑过一个 cron 解决方案来终止缓慢的查询,但这不是很优雅。在生产环境中,查询将每隔几秒调用一次,因此 cron 需要持续运行。
有什么建议吗?
- 版本为 10.1.14-MariaDB
使用 10.1 版中的 MariaDB,您可以通过两种方式来限制查询。它可以基于时间或查询的行总数来完成。
按行:
SELECT ... LIMIT ROWS EXAMINED rows_limit;
您可以使用关键字 EXAMINED
并设置行数,如您提到的 400000 (自 MariaDB 10.0 起)。
按时间:
If the max_statement_time variable is set, any query (excluding stored procedures) taking longer than the value of max_statement_time (specified in seconds) to execute will be aborted. This can be set globally, by session, as well as per user and per query.
如果你想要它用于特定的查询,就像我想象的那样,你可以使用这个:
SET STATEMENT max_statement_time=1 FOR
SELECT field1 FROM table_name ORDER BY field1;
请记住 max_statement_time
是以秒为单位设置的(与 MySQL 相反,后者是毫秒),因此您可以更改它直到找到最适合您的情况 (自 MariaDB 10.1 起)。
如果您需要更多信息,我推荐您 excellent post 关于查询超时的内容。
希望对您有所帮助。