我读过关于FORCE
索引的文章,但是如何强制MySQL索引到IGNORE ALL
索引呢?
我试过SELECT * FROM tbl IGNORE INDEX(*)
,但没有成功。
至于为什么我(和其他人)需要这样做:例如,我需要像这样总结tld的引用统计数据:
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定义表的几十行实际上不是捷径)。
中添加
贝赫马克:
基准的定义:
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秒,我刚刚杀死了它。
发布于 2015-08-11 12:10:01
您还可以嵌入WHERE 1=1
。
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
将恢复为聚集索引。尽管如此,还有另外一种方法,但它需要对优化器有一点恶意。
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
选择一列。
我刚刚在一个临时服务器的一个大表上尝试了这个
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)
不选择索引。
发布于 2015-08-17 17:15:22
假设您有这两个索引:
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之后它就不会起作用了。
https://dba.stackexchange.com/questions/110707
复制