Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询优化_Sql_Mysql_Optimization - Fatal编程技术网

Sql 查询优化

Sql 查询优化,sql,mysql,optimization,Sql,Mysql,Optimization,我有两个问题 第一: SELECT * FROM `table` WHERE col='xyz' LIMIT 100 //Time Taken: 0.0047s 第二: SELECT * FROM `table` WHERE col='xyz' ORDER BY Id DESC LIMIT 100 //Time Taken: 1.8208s 第二个需要更长的时间。我知道这是为什么,因为首先我必须选择整个表,然后进行排序,而第一个查询只返回前100行 有没有其他方法来排序,比如选择最后100行

我有两个问题

第一:

SELECT * FROM `table` WHERE col='xyz' LIMIT 100
//Time Taken: 0.0047s
第二:

SELECT * FROM `table` WHERE col='xyz' ORDER BY Id DESC LIMIT 100
//Time Taken: 1.8208s
第二个需要更长的时间。我知道这是为什么,因为首先我必须选择整个表,然后进行排序,而第一个查询只返回前100行

有没有其他方法来排序,比如选择最后100行,然后进行排序?还是我的查询做错了,可以更快

请注意,Id是自动递增的,因此在排序时,选择最后一行仍将返回正确的数据

CREATE TABLE `table`(
    `Id` BIGINT NOT NULL AUTO_INCREMENT,
    `dateReg` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

    PRIMARY KEY (`Id`)
) ENGINE=MyISAM

您的id列应设置为主键(或者,如果您有其他主键,则应在其上放置索引)。这将大大加快查询速度。

如果您正在为表使用
MyISAM
,请在
(col,id)
上创建一个复合索引

InnoDB
中,
主键作为行指针隐式包含在表中,因为
InnoDB
表是按设计组织索引的

InnoDB
的情况下,要在
(col,id)
上创建一个索引,只需在
col
上创建一个索引,并确保
id
主键

此索引将用于过滤
,并按
id
排序

索引是一个
B-树
结构,因此它可以以相同的效率迭代
ASC
DESC

对于连续ID:

SELECT t.*
  FROM TABLE t
  JOIN (SELECT MAX(t.id) 'maxid'
          FROM TABLE t) max ON t.id BETWEEN max.maxid-100 AND max.maxid
 WHERE t.col = 'xyz' 
SELECT a.*
  FROM (SELECT t.*,
               @rownum := @rownum+1 AS rownum
          FROM TABLE t, (SELECT @rownum := 0) r
         WHERE t.col = 'xyz') a,
       (SELECT COUNT(t.*) 'max'
          FROM TABLE t
         WHERE t.col = 'xyz') m
WHERE a.rownum BETWEEN m.max-100 AND m.max
对于非连续ID:

SELECT t.*
  FROM TABLE t
  JOIN (SELECT MAX(t.id) 'maxid'
          FROM TABLE t) max ON t.id BETWEEN max.maxid-100 AND max.maxid
 WHERE t.col = 'xyz' 
SELECT a.*
  FROM (SELECT t.*,
               @rownum := @rownum+1 AS rownum
          FROM TABLE t, (SELECT @rownum := 0) r
         WHERE t.col = 'xyz') a,
       (SELECT COUNT(t.*) 'max'
          FROM TABLE t
         WHERE t.col = 'xyz') m
WHERE a.rownum BETWEEN m.max-100 AND m.max

如果您在id上使用autoincrement,您可以只选择最后100行吗?^是的,但如何选择最后100行?对于这两个查询,在解释()的结果之前,这将有所帮助。还有,什么是“更长的时间”?每个查询需要多长时间?您的表是
MyISAM
还是
InnoDB
id
a
PRIMARY KEY
?您能发布您的确切表格定义吗?只需运行
showcreatetable`TABLE`
并发布输出。它已被索引。。。同样的问题一个复合索引可能会有所帮助,但是没有办法只选择最后100行而不是前100行
@Shahmir Javaid
:索引可以以同样的效率在两种方式工作。试试看,我会。。但这需要一些时间,因为我必须修复一百万条记录的表。我担心这会导致返回与原始查询相同的结果。当您想要特定数量的记录按特定顺序排列时,需要首先应用顺序。原来的海报似乎并不关心这一点,但稍后阅读此海报的其他人可能没有意识到,当您需要按照您要求的顺序提供前100条记录时,此解决方案存在问题。有点问题:我的数据库正在工作,因此我无法在到达Row之前对其进行测试。然而,我会张贴结果,一旦我得到它@我必须订购最后100行。这对设计很重要,我必须显示数据库中的最后100行。这对我来说更像是一种学术上的好奇——如果不需要的话,我宁愿不使用subselect,但在mySQL(或Postgres)上没有其他选择。我有你所拥有的完全相同的副本。而不是选择最后一个。它首先选择一个,然后对它们进行排序。然而,如果我们可以选择“最后一个”,然后按顺序执行,上述操作将有效treat@rexam你性感的抽泣,似乎在耍花招D….作为旁注,如果id像这样200 199 198 190 189 185,我说它不会返回100条记录,对吗。