高效查询当前插入后记录的自增长ID (原创)
最近在处理客户提出的问题时,发现我所使用的一条SQL语句效率不咋地,该SQL语句用来取得刚刚插入的记录的auto_increment值。
我的SQL长得很象这样:
SELECT MAX(Ref) FROM TbName;
我一度把它变成这样:
SELECT Ref FROM TbName ORDER BY DESC LIMIT 1;
效率高了一点,但还不理想(有观点说MAX比ORDER + LIMIT效率高,且举出多种推测和例证,云云。但我做出来结果的确不同,时间不多,我无法更深入测试,您就爱信信谁去吧)。中间有想过放弃研究SQL,由C++绕。但一边说着放弃,一边还是打开了MySQL的文档,终于,我看到了下面的东东:
LAST_INSERT_ID()
, LAST_INSERT_ID(
expr
)
For MySQL 5.1.12 and later, LAST_INSERT_ID()
(no arguments) returns the first automatically generated value successfully inserted for an AUTO_INCREMENT
column as a result of the most recently executed INSERT
statement. The value of LAST_INSERT_ID()
remains unchanged if no rows are successfully inserted.
好啊,马上改,试,ho ho,效果好的一塌糊涂。我的SQL语句变成这样了:
SELECT LAST_INSERT_ID() AS Ref;
那么,last_insert_id()咋就这么神泥?看了一下MySQL的相关代码(再加上本人的猜测,呵呵,没时间再接着鼓捣啦),原来MySQL维护了一个叫insert_id的变量,在结构st_mysql里,在每一次执行完insert或update后,该变量会被更新。使用LAST_INSERT_ID(),只需直接把这个变量值返回即可。也就是说,它无需做任何运算。而max不然,它需要至少一次遍历,才能找出最大值,LIMIT + ORDER先要做一次排序,两者的效率应该旗鼓相当。
由此,我的结论是,关于效率:
"LAST_INSERT_ID()” > ”LIMIT + ORDER“ >= ”MAX()“
补充两点:
1. MAX()用来取得当前插入ID有一定风险:在您的数据库同时存在多个连接时,如果在一个连接的insert和max()之间有另一连接也对该表执行了insert,则max拿到的将不是您希望的值;
2. LAST_INSERT_ID()是连接安全的:MySQL为每个连接维护了一个st_mysql实例,即使别的连接在同时执行了insert,你也能正确地拿到您刚才产生的ID。