首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何强制MySQL忽略所有索引?

如何强制MySQL忽略所有索引?
EN

Database Administration用户
提问于 2015-08-11 18:04:15
回答 2查看 22.4K关注 0票数 13

我读过关于FORCE索引的文章,但是如何强制MySQL索引到IGNORE ALL索引呢?

我试过SELECT * FROM tbl IGNORE INDEX(*),但没有成功。

至于为什么我(和其他人)需要这样做:例如,我需要像这样总结tld的引用统计数据:

代码语言:javascript
运行
复制
SELECT 
    count(*) as c, 
    SUBSTRING
    (
        domain_name, 
        LENGTH(domain_name) - LOCATE('.', REVERSE(domain_name)) + 2
    ) as tld
FROM `domains_import` 
    IGNORE INDEX(domain_name)
GROUP BY tld
ORDER BY c desc
LIMIT 100

...but --我总是要查看定义了哪些索引,或者通过解释来确定将使用什么索引。简单地编写IGNORE INDEX ALL而不关心它将是非常方便的。

有人知道语法或黑客吗?(通过MySQL定义表的几十行实际上不是捷径)。

聊天讨论:

中添加

贝赫马克:

  • 无指数= 148.5秒
  • 由于索引= 180秒,并且仍然在发送数据时,SSD数组非常强大,因此您几乎不关心数据缓存.

基准的定义:

代码语言:javascript
运行
复制
CREATE TABLE IF NOT EXISTS `domains_import` (
`domain_id` bigint(20) unsigned NOT NULL,
`domain_name` varchar(253) CHARACTER SET ascii COLLATE ascii_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `domains_import`
ADD PRIMARY KEY (`domain_id`),
ADD UNIQUE KEY `domain_name` (`domain_name`);

ALTER TABLE `domains_import`
MODIFY `domain_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT;

InnoDB,带有索引的测试(没有使用索引()或类似的)仍然在运行,250秒,我刚刚杀死了它。

EN

回答 2

Database Administration用户

发布于 2015-08-11 20:10:01

您还可以嵌入WHERE 1=1

代码语言:javascript
运行
复制
SELECT 
    count(*) as c, 
    SUBSTRING
    (
        domain_name, 
        LENGTH(domain_name) - LOCATE('.', REVERSE(domain_name)) + 2
    ) as tld
FROM `domains_import` 
WHERE 1=1
GROUP BY tld
ORDER BY c desc
LIMIT 100

约伯刚问我

Rolando,MySQL的优化器是如此愚蠢,以至于一个简单的总是真实的条件将禁止使用索引吗?

是的,但是您已经给了MySQL一个非常愚蠢的查询。1=1将恢复为聚集索引。尽管如此,还有另外一种方法,但它需要对优化器有一点恶意。

代码语言:javascript
运行
复制
SELECT 
    count(*) as c, 
    SUBSTRING
    (
        domain_name, 
        LENGTH(domain_name) - LOCATE('.', REVERSE(domain_name)) + 2
    ) as tld
FROM `domains_import` 
WHERE domain_name = domain_name
GROUP BY tld
ORDER BY c desc
LIMIT 100

这肯定会抛出总线下的每个索引,因为每一行的domain_name值都会被选中。如果domain_name是索引的,则必须为根本没有索引的WHERE column_name=column_name选择一列。

我刚刚在一个临时服务器的一个大表上尝试了这个

代码语言:javascript
运行
复制
mysql > explain SELECT COUNT(1) FROM VIDEO WHERE EMBEDDED_FLG=EMBEDDED_FLG;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | VIDEO | ALL  | NULL          | NULL | NULL    | NULL | 354327 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)

不选择索引。

票数 2
EN

Database Administration用户

发布于 2015-08-18 01:15:22

假设您有这两个索引:

代码语言:javascript
运行
复制
ADD PRIMARY KEY (`domain_id`),
ADD UNIQUE KEY `domain_name` (`domain_name`);

那么,优化器做什么并不重要;它必须从本质上扫描相同数量的东西。

案例1:它进行表扫描(或使用domain_id):它将扫描(id、name)对、定位所有名称、执行SUBSTRING..LOCATE、GROUP BY、最后ORDER。GROUP和ORDER可能都需要一个tmp表和文件。检查EXPLAIN SELECT ...,看看是否有。

案例2:它进行索引扫描( domain_name):该索引实际上包含(名称、id)对--因为InnoDB隐式地将PK放置在任何辅助键的末尾。其余的处理与案例1平行。

有一件事可能是不同的--两个BTrees的大小。执行SHOW TABLE STATUS LIKE domains_import以查看Data_length (用于案例1)和Index_length (用于案例2)。较大的BTree会变慢。

另一件事可能是不同的--缓存。innodb_buffer_pool_size的价值是什么?你有多少内存?数据(或索引)是否包含在缓冲池中?(或者说是37%,因为这是一个表/索引扫描?)如果符合,那么运行查询两次。第二次将是大约10倍的速度,因为没有击中磁盘(缓存)。

如果这是一次任务,SSD将有所帮助.如果没有,并且您可以缓存整个表,那么在加载buffer_pool之后它就不会起作用了。

票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/110707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档