【问题标题】:Codeigniter sessions class w/ database storage option not optimized?未优化带有数据库存储选项的 Codeigniter 会话类?
【发布时间】:2011-10-18 07:54:16
【问题描述】:

我使用 codeigniter 的会话类,可以选择将会话数据存储在数据库中。这是为每个用户请求运行以检索会话的选择查询示例:

SELECT *
FROM (`ci_sessions`)
WHERE `session_id` = 'f7fd61f08a229kdu3093130a3da17e14'
AND `user_agent` = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.'

这是user guide中定义的会话数据的表结构:

CREATE TABLE IF NOT EXISTS  `ci_sessions` (
session_id varchar(40) DEFAULT '0' NOT NULL,
ip_address varchar(16) DEFAULT '0' NOT NULL,
user_agent varchar(50) NOT NULL,
last_activity int(10) unsigned DEFAULT 0 NOT NULL,
user_data text DEFAULT '' NOT NULL,
PRIMARY KEY (session_id)
);

我的理解是,每当您有一个旨在返回单个结果的查询时,最好使用 LIMIT 0, 1 以便当数据库引擎找到所需的行时它只是返回而不是继续扫描整个表更多比赛。因此,将这个查询写成这样会更有效吗:

SELECT *
FROM (`ci_sessions`)
WHERE `session_id` = 'f7fd61f08a229kdu3093130a3da17e14'
AND `user_agent` = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.'
LIMIT 0, 1

有什么理由没有这样写吗?

【问题讨论】:

  • 如果你有多个匹配的行,这首先是一个很大的负面因素;)如果你的代码被设计为期望单行,这至少会引发一个致命错误
  • 我自己对此感到好奇。查看 Session 类源代码后,我认为没有理由不使用 LIMIT 子句。他们也使用row() 来获取数据,它只返回 first 行...
  • @Casey:确实,这似乎没有优化,即使 CI 使用游标获取。此外,如果只获取一个(且唯一的)行,则不需要使用 offset 参数,LIMIT 1 会做得很好并且应该更快(不确定它是否实际上更有效,但它会有意义)。
  • 欢迎有根据地推测为什么在这种情况下不使用 LIMIT。我在 CI Core 或 Reactor bitbucket 问题中没有看到与此相关的任何内容,因此可能会给他们带来一些东西。如果确实没有理由使用这种简单的单行优化。
  • 现在,我当然没有受过良好的 SQL 或数据库性能方面的教育(阅读:noob),但 session_id 是主键这一事实与 LIMIT 1 无关是优化?

标签: mysql codeigniter session-state php


【解决方案1】:

可能只有一行,匹配user_agent和session_id,所以不需要限制选择的数量,它已经被唯一的限制了。

该问题已在 Bitbucket 上报告给 Codeigniter Reactor 开发人员,并因无效而被驳回:

https://bitbucket.org/ellislab/codeigniter-reactor/issue/422/session-class-should-use-limit-1-when

他们的回应:

session_id 字段是主键,因此它将是唯一的行

Is there any point using MySQL "LIMIT 1" when querying on indexed/unique field?

所以看起来这实际上不是优化,它只是不必要的。

【讨论】:

  • 不正确/不清楚的答案:没有 LIMIT,将在整个表中搜索与 WHERE 子句匹配的值。可能有数千条记录,因此这会影响性能。 应该只有一行,即使出于某种原因还有更多,CI也只返回第一个。
  • 创建一个二分搜索功能,您将避免进入searchnig所有记录。线性搜索不是很快。我不知道你为什么这么担心,反正你可能不会有什么不同。但是,是的,如果你真的想改变一些事情,通过 SQL 进行二进制搜索。
  • @Grigor,看到这个问题的第一个回复:stackoverflow.com/questions/1787275/…
  • 这可能是一个性能问题的原因是这个查询是针对每个用户发起的每个页面请求执行的。在任何给定时间都可能有数千个处于活动状态的用户会话的站点会因为 DBMS 在已经找到它正在寻找的会话之后花费在搜索会话表的其余部分上所花费的额外时间而看到复合的性能损失
  • 看起来你是对的 Grigor,我向开发团队报告了它,他们说这是不必要的,并引用了另一个 Stack Overflow 帖子。我对此感觉更舒服,感谢您的加入 - 就我而言,这已解决。为我在第一条评论中的傲慢语气道歉。不过,我希望听到比单线更好的解释。我仍然需要等待至少 14 小时才能获得赏金,所以请随意添加一个,这样答案就可以独立了。
猜你喜欢
  • 1970-01-01
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 2011-01-05
相关资源
最近更新 更多