【发布时间】:2012-09-11 07:42:52
【问题描述】:
尝试根据无孔的自动递增主键从表中选择随机行。
表架构:
CREATE TABLE IF NOT EXISTS `testTable` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`data` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;
INSERT INTO `testTable` (`id`, `data`) VALUES
(1, 'hello'),
(2, 'world'),
(3, 'new'),
(4, 'data'),
(5, 'more and more'),
(6, 'data '),
(7, 'more rows here'),
(8, 'most rows here'),
(9, 'testing'),
(10,'last');
查询:
1/explain select * from testTable where id = ceil(Rand()*10) limit 1 ;
http://sqlfiddle.com/#!2/6e2b1/1
结果:
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY | KEY_LEN | REF | ROWS | EXTRA |
--------------------------------------------------------------------------------------------------------
| 1 | SIMPLE | testTable | ALL | (null) | (null) | (null) | (null) | 10 | Using where |
2/explain select * from testTable where id = 7 limit 1 ;
http://sqlfiddle.com/#!2/6e2b1/2
结果:
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY | KEY_LEN | REF | ROWS | EXTRA |
---------------------------------------------------------------------------------------------------
| 1 | SIMPLE | testTable | const | PRIMARY | PRIMARY | 4 | const | 1 | |
为什么 query#1 不使用索引,而 ceil(rand()*10) 应该理想地评估为一个常量,然后可以将其与主键进行比较?优化器不应该那样工作吗?还是我在这里遗漏了一些明显的东西。
【问题讨论】:
-
在 WHERE 条件下使用函数(如 ceil/rand)会导致系统首先获取所有行,以便能够将结果与该函数的每个结果进行比较。您最好使用“外部”选择来获取随机整数值,然后使用它来获取您的主键。
标签: mysql