慢查询引起的MySQL数据库转换为varcharint

最近一周处理2慢查询已被索引的int引起varchar转换。




创建表(` appstat_day_prototype_201305 `
` day_key `日期不为空的默认'1900-01-01,
`所` varchar(20)不为空的默认,
` user_total ` bigint(20)不为空的默认'0',
` user_activity ` bigint(20)不为空的默认'0',
` times_total ` bigint(20)不为空的默认'0',
` times_activity ` bigint(20)不为空的默认'0',
` incr_login_daily ` bigint(20)不为空的默认'0',
` unbind_total ` bigint(20)不为空的默认'0',
` unbind_activitys ` bigint(20)不为空的默认'0',
主键(`所`,` day_key `)
InnoDB引擎=默认的字符集utf8)
MySQL >解释选择*从appstat_day_prototype_201305那里所xxxxx和day_key之间'2013-05-23=。
+ -- + + + + ------------- ------------------------------ ------ --------------- + ------ + --------- + ------ ---------- ------------- + + +
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+ -- + + + + ------------- ------------------------------ ------ --------------- + ------ + --------- + ------ ---------- ------------- + + +
| 1 |简单| appstat_day_prototype_201305 |所有|主要零零零| | | | 19285787 |使用|
+ -- + + + + ------------- ------------------------------ ------ --------------- + ------ + --------- + ------ ---------- ------------- + + +
1行集(0秒)
MySQL >解释选择*从appstat_day_prototype_201305那里所xxxxxday_key之间'2013-05-23 = ' '。
+ -- + + + + ------------- ------------------------------ ------- --------------- + --------- + --------- + ------ ------ ------------- + + +
我select_type表| | | |型possible_keys关键key_len | | | | REF |行|额外|
+ -- + + + + ------------- ------------------------------ ------- --------------- + --------- + --------- + ------ ------ ------------- + + +
| 1 |简单| appstat_day_prototype_201305范围初级| | | | 65 |空| 1 |使用|
+ -- + + + + ------------- ------------------------------ ------- --------------- + --------- + --------- + ------ ------ ------------- + + +
1行集(0秒)


从以上可以看出,作为appkey VARCHAR和在没有',将导致全表查询,你可以使用这个指标,扫描线,但对服务器的压力和自然的响应时间不同也不同。



让我们看另一个例子。




*************************** 1。行***************************
表:poll_joined_151
表的创建:创建表(` poll_joined_151 `
` poll_id ` bigint(11)不为空,
`uid` bigint (11) NOT NULL,
` item_id ` varchar(60)不为空,
` add_time ` int(11)不为空的默认'0',
`匿名` tinyint(1)不为空的默认'0',
` sub_item ` varchar(1200)不为空的默认,
关键` idx_poll_id_uid_add_time `(` poll_id `,` UID `,` add_time `),
关键` idx_anonymous_id_addtime `(`匿名`,` poll_id `,` add_time `)
InnoDB引擎=默认的字符集utf8)
SELECT * FROM poll_joined_151哪里poll_id = '2348993'and匿名= 0阶的add_time = 0, 3
*************************** 1。行***************************
编号:1
select_type:简单
表:poll_joined_151
类型:裁判
possible_keys:idx_poll_id_uid_add_time,idx_anonymous_id_addtime
关键词:idx_anonymous_id_addtime
key_len:9
常量常量
行数:30240
附加:使用在哪里


从上面的例子,虽然poll_id类型为bigint,SQL已经增加了,但这句话仍然使用的指标,虽然扫描线的数量也很多,但索引可以很好的SQL。



那么,为什么会有这么大的影响呢最根本的原因是MySQL在比较文本类型和数字类型时进行隐式转换。

以下是5.5官方手册的说明:




如果比较操作中的两个参数都是字符串,则将它们进行比较。
两个参数是一个字符串,它与没有类型转换的字符串进行比较。
如果两个参数都是整数,则将它们作为整数进行比较。
这两个参数都是整数,与整数比较,不进行类型转换。
十六进制值被视为二进制字符串,如果不与
当十六的值与非数字比较时,它将被视为二进制字符串。
如果一个参数是一个时间戳或datetime列和其他参数是一个常数,该常数转换为时间戳,再进行比较。这样做是为了更友好的ODBC。注意,这不是为了安全的参数而做的,总是使用!完成的日期,日期或时间字符串做比较时。例如,在使用日期或时间值之间取得最佳效果时,使用CAST(to)显式地将值转换为所需的数据类型。
一个参数的时间或日期,和其他的参数是常数,并不断将转换为时间戳
如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,或者如果另一个参数是浮点值,则将浮点值作为十进制值进行比较。
一个参数是十进制类型。如果另一个参数是十进制或整数,它将将整数转换为十进制。如果另一个参数是浮点数,它会将十进制转换为浮点数以便比较。
在所有其他情况下,参数被比较为浮点(实数)实数,所有其他情况下,所有两个参数都将被转换为浮点数以便比较。


根据上面的解释,当位置值与表结构不一致时,MySQL将进行隐式转换,并将其转换为浮点数。



对于第一种情况:



例如,字符串= 1;



将索引中的字符串转换为浮点数是必要的。然而,因为‘1','1a'will被转换为1,MySQL无法使用索引扫描表完全,导致慢查询生成。




MySQL >选择投(1为符号)= 1;
------------------------- + +
|铸造(1'signed = 1 |)
------------------------- + +
1 | |
------------------------- + +
1行集(0秒)
MySQL >选择投('1a签署)= 1;
-------------------------- + +
|铸造(1a'signed = 1 |)
-------------------------- + +
1 | |
-------------------------- + +
1排,1警告(0秒)
MySQL >选择投('1'as签署)= 1;
----------------------- + +
|铸('1'as签署)= 1 |
----------------------- + +
1 | |
----------------------- + +
1行集(0秒)


同时,我们需要注意的是,因为他们都将被转换为浮点数,和浮点数仅为53bit,所以当最大值超标,会有更多的问题。



第二例:



由于索引是建立在int上的,并且纯数字的数目可以被转换为100%的数字,它可以用来索引,虽然它也会进行一些转换和消耗某些资源,但最后仍然使用索引,并且不会产生缓慢的查询。




MySQL >选择投('30'as签署)= 30;
---------------------------- + +
|铸('30'as签署)= 30 |
---------------------------- + +
1 | |
---------------------------- + +
1行集(0秒)


以上是一个缓慢的查询是通过在MySQL数据库中,经Xiaobi介绍到varchar转换触发int。希望能对你有所帮助。如果你有任何问题,请给我留言,萧边会及时给您回复。谢谢您支持网站。