小内存表中主键的简单常量选择非常慢

发布于 2024-12-11 12:25:29 字数 665 浏览 0 评论 0原文

我有一个 MEMORY 表,大约有 650 行,5 MB 数据长度,60 kB 索引长度(所以它非常小)。它有一个 SMALLINT 主(哈希)键,以及大约 90 个其他列(整数、varchar、日期时间,无 blob 或文本)。 (编辑:BIGINT 列上还有一个哈希键。)

我经常运行此查询(从 PHP)(大约每秒 10 次):

从 userek 中选择 *,其中 id={CONST_ID} 且 kitiltva=0 且 kitiltva_meddig<“{CONST_DATETIME}”和 inaktiv=0

注意:id 是主键。我需要 * 因为结果在很多不同的地方使用,并且基本上所有列都在这里或那里使用。

我的问题是:查询经常变得异常缓慢。平均大约0.5s,最多8s。大多数时候它的速度非常快:75% 的运行速度比 3ms 快,85% 比平均水平快。但15%比平均速度慢,13%1s慢。所以它有一条长尾巴。

我完全不知道是什么原因造成的。有人有什么想法吗?

I have a MEMORY table with about 650 rows, 5 MB data length, 60 kB index length (so it's pretty small). It has one SMALLINT primary (hash) key, and about 90 other columns (ints, varchars, datetimes, no blobs or texts). (EDIT: there's also a hash key on a BIGINT column.)

I'm running this query (from PHP) quite often (about 10 times per second):

select * from userek where id={CONST_ID} and kitiltva=0 and
kitiltva_meddig<"{CONST_DATETIME}" and inaktiv=0

Note: id is the primary key. I need the * because the result is used in a lot of different places, and basically all columns are used here or there.

My problem is: the query gets abnormally slow on a regular basis. About 0.5s on average, 8s max. Most of the times it's very fast: 75% of runs faster than 3ms, 85% faster than the average. But 15% it's slower than average, 13% slower than 1s. So it's got a long tail.

And I have absolutely no idea what might cause it. Any thoughts anyone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

段念尘 2024-12-18 12:25:29

很抱歉回答我自己的问题,但至少我有一个答案。我尝试以对其他人有帮助的方式来编写它。

由于它是 MEMORY 表,因此我排除了 I/O 问题。

接下来,查询是通过主键进行的简单(const)选择,因此它也不可能是索引问题。

下一个猜测是锁定。我的应用程序在此表上有一些非常慢的选择。这可能是一个问题:慢速选择延迟更新,从而延迟其他选择,因此最终这个非常简单且快速的选择可能会被延迟。

我检查了慢速查询日志,发现使用此特定表(以及其他表)的两个频繁且缓慢的选择。原因是案例中的联接格式不正确:

A left join B on case
when A.x=1 then B.id=A.id2
when A.x=2 then B.id=A.id3
else B.id=0
end

“两者”没有

A left join B on B.id = case
when A.x=1 then A.id2
when A.x=2 then A.id3
else 0
end

给出相同的结果,但后者可以使用 B.id 的索引,而前者则不能。

一旦我更正了这些查询,原始查询的性能就得到了极大的增强:平均5ms而不是500ms。并且比平均速度快 98%

寓意:

  • 使用慢速查询日志,对其进行分析,
  • 如果遇到莫名其妙的速度变慢,则改进慢速查询,始终检查通过锁定同一个表来减慢查询速度的“交叉”查询

Sorry for answering my own question, but at least I have an answer. I try to write it in a such a way that's helpful for others.

Since it's a MEMORY table, I excluded I/O problems.

Next, the query is a simple (const) select by the primary key, so it cannot be an indexing problem either.

The next guess was locking. There are/were some very slow selects in my application on this table. And it can be a problem: slow selects delay updates that delay other selects, so in the end this very simple and fast select can be delayed.

I checked the slow query log and found two frequent and slow selects that were using this particular table (and others as well). The cause was a badly formed join on a case:

A left join B on case
when A.x=1 then B.id=A.id2
when A.x=2 then B.id=A.id3
else B.id=0
end

instead of

A left join B on B.id = case
when A.x=1 then A.id2
when A.x=2 then A.id3
else 0
end

Both give the same result, but the latter can use an index of B.id, the former cannot.

Once I corrected these queries the performance of the original query was greatly enhanced: 5ms instead of 500ms on average. And 98% faster than average.

The moral:

  • use slow query log, analyse it, and improve slow queries
  • if you encounter inexplicable slow-downs, always check for "crossing" queries that slow down your query by locking the same table
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文