我有这张桌子:
CREATE TABLE `messenger_contacts` (
`number` varchar(15) NOT NULL,
`has_telegram` tinyint(1) NOT NULL DEFAULT '0',
`geo_state` int(11) NOT NULL DEFAULT '0',
`geo_city` int(11) NOT NULL DEFAULT '0',
`geo_postal` int(11) NOT NULL DEFAULT '0',
`operator` tinyint(1) NOT NULL DEFAULT '0',
`type` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `messenger_contacts`
ADD PRIMARY KEY (`number`),
ADD KEY `geo_city` (`geo_city`),
ADD KEY `geo_postal` (`geo_postal`),
ADD KEY `type` (`type`),
ADD KEY `type1` (`operator`),
ADD KEY `has_telegram` (`has_telegram`),
ADD KEY `geo_state` (`geo_state`);
有大约1100万条记录。
这个表上的简单计数选择需要大约30到60秒才能完成女巫似乎非常高。
select count(number) from messenger_contacts where geo_state=1
我不是数据库专家,所以除了设置索引我不知道还能做些什么来加快查询速度?
更新:
好的,我对列类型和大小进行了一些更改:
CREATE TABLE IF NOT EXISTS `messenger_contacts` (
`number` bigint(13) unsigned NOT NULL,
`has_telegram` tinyint(1) NOT NULL DEFAULT '0' ,
`geo_state` int(2) NOT NULL DEFAULT '0',
`geo_city` int(4) NOT NULL DEFAULT '0',
`geo_postal` int(10) NOT NULL DEFAULT '0',
`operator` tinyint(1) NOT NULL DEFAULT '0' ,
`type` tinyint(1) NOT NULL DEFAULT '0' ,
PRIMARY KEY (`number`),
KEY `has_telegram` (`has_telegram`,`geo_state`),
KEY `geo_city` (`geo_city`),
KEY `geo_postal` (`geo_postal`),
KEY `type` (`type`),
KEY `type1` (`operator`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
现在,*
和number
坦克为你提供帮助,甚至是给我-1
的人。考虑到我的服务器是低端硬件而且我将缓存select count
结果,这就足够了。
答案 0 :(得分:0)
也许
select count(geo_state) from messenger_contacts where geo_state=1
因为它会给出相同的结果但不会使用聚集索引中的数字列吗?
如果这没有帮助,我会尝试将数字列更改为INT类型,这应该减少索引大小,或者尝试增加MySQL可用于缓存索引的内存量。
答案 1 :(得分:0)
您没有更改数据类型。 INT(11)
== INT(2)
== INT(100)
- 每个都是一个4字节有符号整数。您可能需要1字节无符号TINYINT UNSIGNED
或2字节SMALLINT UNSIGNED
。
将“标志”编入索引是浪费,我假设type
和has_telegram
。优化器永远不会使用它们,因为它的效率低于简单的表扫描效果。
标准编码模式是:
select count(*)
from messenger_contacts
where geo_state=1
除非您不需要计算NULLs
,COUNT(geo_state)
暗示的内容。
在geo_state
(或索引以geo_state
开头)上有索引后,查询将扫描索引(这是一个单独的BTree结构),从第一次出现geo_state=1
直到最后一次出现,算起来。也就是说,它将触及1.1百万个索引条目。所以,预计几秒钟。计算“罕见”geo_state
的速度会快得多。
30-60秒与4-5秒的原因很可能是缓存。前者必须从磁盘中读取内容;后者没有。运行查询两次。
使用geo_state
索引 查询比使用PRIMARY KEY
更快,除非存在缓存差异。
INDEX(number,geo_state)
对于SELECTs
提到的任何geo_state
实际上都是无用的 - select count(number)...
应该是第一位的。这是var me = this,
toastConfig = {
top: 10,
right: 10,
timeout: 5000,
hideOnMaskTap : true,
message: '<div style="text-align: left; font-size: 14px;">' +
' <p style="font-size:12px;text-align: center;margin-bottom: 8px;">New Message</p>' +
' <p><b>' + receivedMessage.Sender + ' : </b></p>' +
' <p>' + Ext.util.Format.ellipsis(Ext.util.Format.htmlEncode(receivedMessage.MessageBody), 80) + '</p>' +
'</div>'
};
var toastWindow = Ext.toast(toastConfig);
var msg_toast = document.getElementsByClassName('x-toast')[0];
if(msg_toast){
msg_toast.addEventListener(
"touchend",
function(){
me.showMsgPanel();
toastWindow.hide();
},
true
);
}
案例的“覆盖”索引的示例。