【发布时间】:2025-12-07 07:55:02
【问题描述】:
我有一个用于工业机器的简单软件,它使用 MySQL 作为数据存储。任何时候数据库上只有一个连接和一个用户。
我的表很简单:
id data fetched
int varchar boolean
1 KDINNALSKDGJ 0
2 F34LNALNLIJA 0
等等。 id 总是连续的,并且有一个索引。
我需要的是始终获取第一个“数据”(具有最低 id),其中 fetched 为 0。然后将“fetched”更新为“1”,因为我收到了数据。
我使用类似的东西
SELECT id, data FROM mytable WHERE fetched=0 LIMIT 0,1
这可行,但每次调用都会按顺序变慢。这是我真正的问题。我可以忍受前 100 秒左右的估计 0,005 秒,但在 50.000+ 时,我会遇到 0.3 秒。
我认为这是因为数据库每次查找第一个匹配项时都会从顶部搜索。
按数字约束索引要快得多:
SELECT id, data FROM mytable WHERE id> :myLastID and fetched=0 LIMIT 0,1
.. 但这在 40.000 左右之后也会变慢,在 80.000 处我大约是 20 毫秒(第一次大约是 6 毫秒)
我的最终数据库可能在数百万范围内,但通常可能在 2-500.000 左右
有什么方法可以让 MySQL 更快地返回“下一条记录”?使用 MySQL 中的 CURSOR 吗?
我将使用 Delphi 来连接 MySQL。我尝试了存储过程并使用 2 个查询来选择 /update。结果几乎一样。
【问题讨论】:
-
你试过'TOP'吗?我不知道它是否适用于 MySQL,但它应该。 w3schools.com/sql/sql_top.asp
-
请注意,没有 ORDER BY 的 LIMIT 是毫无意义的
-
看来您需要的是 UPDATE,而不是 SELECT
-
@P2000 我必须保留数据,因为我稍后会做报告。数据的处理不仅仅是“获取” - 也可以是“处理”和“验证”。我想我最终会得到“查询大块”,然后用事务批量更新。在断电时当然会冒着不一致的风险,我试图用单一查询的想法来防止这种情况。
-
是的,如果您缓存在易失性内存上,电源中断是一个问题,当然,这就是 S/W 结构/变量所在的位置。您可以在数据库表中镜像加载的缓存/块“数组”。如果镜像在并发线程中,则可以最大限度地减少延迟问题。我猜你知道这一点:如果操作系统仍在内存中缓冲 R/W,即使 DB 也可能不安全。电源中断最好在 H/W 级别使用 UPS 和断电中断来处理,以退出已知和安全的状态(服务器、医疗设备、机械、军事设备......)
标签: mysql sql delphi sql-order-by query-optimization