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 版中的 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 关于查询超时的内容。

希望对您有所帮助。