sta*_*ack 2 mysql sorting sql-order-by
我有一张桌子
CREATE TABLE `tableMain` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`value1` varchar(45) NOT NULL,
'value2' varchar(50) NOT NULL,
'value3' int NOT NULL,
'value4' timestamp NOT NULL,
'value5' int NOT NULL
PRIMARY KEY (`id`)
)
Run Code Online (Sandbox Code Playgroud)
所以我创建了那个表,我希望它总是按 value2 排序,如果有两个 a like,它应该按 value3 排序,然后按 value4 排序。
所以我试着这样做
ALTER TABLE tableMain
ORDER BY value2 ASC, value3 ASC, value4 ASC
Run Code Online (Sandbox Code Playgroud)
当我运行该代码时,出现错误:
错误代码:1105。ORDER BY 被忽略,因为表 'tableMain' 中有一个用户定义的聚集索引
我想补充一点,我把它作为学校的作业,其他有相同任务的人可以运行这个 ALTER TABLE 行。所以我有点困惑,不知道该怎么办。
如果需要特定序列中的行,请ORDER BY在查询中指定适当的子句。
表中的行需要“排序”的想法与关系数据库理论背道而驰。
关系是一组元组;改变关系中元组的“顺序”不会改变关系。
将理论转化为实践,使用 InnoDB 存储引擎,指定ORDER BY为表属性没有意义,因为 InnoDB 表将始终按其集群索引排序。
对于 MyISAM 存储引擎,指定ORDER BY可能会提高某些查询的性能。该ALTER TABLE ... ORDER BY语句仅重组表一次。运行后续DELETE,INSERT和UPDATE语句时,可能不会保留行的“顺序” 。
重申:如果您需要以特定顺序返回行,则不能依赖于行物理存储在表中的“顺序”。您必须ORDER BY在查询中包含。
要真正提高大表的性能,添加适当的索引是必经之路。
至于为什么你的同学让语句运行,你的语句返回错误……最可能的解释是他们的表使用的是MyISAM存储引擎,而你的表使用的是InnoDB存储引擎。
(无论您的任务是什么,更改表的存储引擎都不是正确的答案……MyISAM 存储引擎是某些用例的合适选择;但 InnoDB 是传统“关系数据库”用例的最合适选择。 )
如果您的要求是您的 InnoDB 表“始终按”一组列(无论出于何种原因)进行排序,则让集群索引将这些列作为前导列包含在内。您可以通过将这些列声明为表的 PRIMARY KEY 的前导列来做到这一点。您可以在id列上创建唯一索引。
CREATE TABLE `tableMain`
( `id` INT(11) NOT NULL AUTO_INCREMENT
, `value1` VARCHAR(45) NOT NULL
, `value2` VARCHAR(50) NOT NULL
, `value3` INT NOT NULL
, `value4` TIMESTAMP NOT NULL
, `value5` INT NOT NULL
, PRIMARY KEY (`value2`,`value3`,`value4`,`id`)
, UNIQUE KEY `tableMain_UX1` (`id`)
)
Run Code Online (Sandbox Code Playgroud)
实际上,我们永远不会这样做……因为任何二级索引都将包含 PRIMARY KEY 值作为返回集群索引的“指针”,这将是一种令人难以置信的资源浪费。在实践中,我们将id作为表的 PRIMARY KEY保留,并在其他列上创建二级索引......
CREATE TABLE `tableMain`
( `id` INT(11) NOT NULL AUTO_INCREMENT
, `value1` VARCHAR(45) NOT NULL
, `value2` VARCHAR(50) NOT NULL
, `value3` INT NOT NULL
, `value4` TIMESTAMP NOT NULL
, `value5` INT NOT NULL
, PRIMARY KEY (`id`)
, KEY `tableMain_IX1` (`value2`,`value3`,`value4`)
)
Run Code Online (Sandbox Code Playgroud)