我在MySQL中有一个包含1000万行和2 GB数据的表 选择IN LIFO格式数据很慢
表格引擎 = int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
android.Manifest.permission.WRITE_CALENDAR);
表格中有一个主键和一个唯一键
InnoDB
我如何提高表的性能。 ?
表格结构
SELECT * FROM link LIMIT 999999 , 50;
注意:
id int(11) NO PRI NULL auto_increment
url varchar(255) NO UNI NULL
website varchar(100) NO NULL
state varchar(10) NO NULL
type varchar(100) NO NULL
prio varchar(100) YES NULL
change varchar(100) YES NULL
last varchar(100) YES NULL
正在SELECT * FROM link LIMIT 1 , 50;
,但是当前的SQL正在花费.9ms
100次更多
答案 0 :(得分:5)
这很可能是由于“早期行查找”
可以强制MySQL进行“后期行查找”。请尝试以下查询
SELECT l.*
FROM (
SELECT id
FROM link
ORDER BY
id
LIMIT 999999 , 50
) q
JOIN link l
ON l.id = q.id
查看这篇文章
答案 1 :(得分:5)
对于下一步和上一页按钮,您可以使用WHERE
子句代替OFFSET
。
示例(使用LIMIT 10
- 下面说明的示例数据):您在某个页面上显示10行,其中包含ID [2522,2520,2514,2513,2509,2508,2506,2504,2497,2496]
。在我的情况下,这是用
select *
from link l
order by l.id desc
limit 10
offset 999000
对于下一页,您将使用
limit 10
offset 999010
获取带有[2495,2494,2493,2492,2491,2487,2483,2481,2479,2475]
的行。
对于上一页,您将使用
limit 10
offset 998990
获取带有[2542,2541,2540,2538,2535,2533,2530,2527,2525,2524]
的行。
以上所有查询都在 500毫秒中执行。使用"技巧" Sanj建议它仍然需要 250毫秒。
现在,使用minId=2496
和maxId=2522
的给定页面,我们可以使用{{1}为 Next 和 Last 按钮创建查询条款。
下一步按钮:
WHERE
结果ID:select *
from link l
where l.id < :minId -- =2496
order by l.id desc
limit 10
。
上一页按钮:
[2495,2494,2493,2492,2491,2487,2483,2481,2479,2475]
结果ID:select *
from link l
where l.id > :maxId -- =2522
order by l.id asc
limit 10
。
要颠倒顺序,您可以在子选择中使用查询:
[2524,2525,2527,2530,2533,2535,2538,2540,2541,2542]
结果ID:select *
from (
select *
from link l
where l.id > 2522
order by l.id asc
limit 10
) sub
order by id desc
。
这些查询在&#34; no time&#34;中执行。 (小于1毫秒)并提供相同的结果。
您无法使用此解决方案来创建页码。但我不认为你会输出200K的页码。
测试数据:
使用
创建了用于示例和基准的数据[2542,2541,2540,2538,2535,2533,2530,2527,2525,2524]
其中CREATE TABLE `link` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`url` VARCHAR(255) NOT NULL,
`website` VARCHAR(100) NULL DEFAULT NULL,
`state` VARCHAR(10) NULL DEFAULT NULL,
`type` VARCHAR(100) NULL DEFAULT NULL,
`prio` VARCHAR(100) NULL DEFAULT NULL,
`change` VARCHAR(100) NULL DEFAULT NULL,
`last` VARCHAR(100) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `url` (`url`)
) COLLATE='utf8_general_ci' ENGINE=InnoDB;
insert into link
select i.id
, concat(id, '-', rand()) url
, rand() website
, rand() state
, rand() `type`
, rand() prio
, rand() `change`
, rand() `last`
from test._dummy_indexes_2p23 i
where i.id <= 2000000
and rand() < 0.5
是一个包含2 ^ 23个ID(约8M)的表。因此,数据包含每隔一个id随机丢失的大约1M行。表大小:228 MB
答案 2 :(得分:0)
我已将SQL查询更新为此,这花费的时间更少。
SELECT * FROM link ORDER BY id LIMIT 999999 , 50 ;
答案 3 :(得分:0)
由于数据量很大,
提高查询响应时间的提示很少:
由于
答案 4 :(得分:0)
首先在没有任何订单的情况下在您的桌面上运行不保证您的查询如果运行两次将返回相同的数据。
最好添加ORDER BY
子句。将id
作为一个好的候选人,因为它是您的主键并且看起来很独特(因为它是auto_increment
值。)
您可以将此作为基础:
SELECT * FROM link ORDER BY id LIMIT 50;
这将为您提供表格中的前50行。
现在接下来的50行,我们可以保存查询中的最后一个位置,而不是使用OFFSET
。
您可以保存上一个查询中最后一行ID的ID,并在下一个查询中使用它:
SELECT * FROM link WHERE id > last_id ORDER BY id LIMIT 50;
这将为您提供最后一个ID之后的下50行。
查询在OFFSET
的高值上运行缓慢的原因是因为mysql必须在给定OFFSET
的所有行上运行并返回最后LIMIT
行数。这意味着较大的OFFSET
是查询运行得越慢。
我上面显示的解决方案不依赖于OFFSET
,因此查询将以与当前页面无关的相同速度运行。
另请参阅此有用的文章,其中介绍了您可以选择的其他一些选项:http://www.iheavy.com/2013/06/19/3-ways-to-optimize-for-paging-in-mysql/