Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.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
Mysql 为JOIN+正确设置索引,如xyz%查询 编辑3:真正的问题是:_Mysql_Indexing_Query Optimization_Database Performance_Query Performance - Fatal编程技术网

Mysql 为JOIN+正确设置索引,如xyz%查询 编辑3:真正的问题是:

Mysql 为JOIN+正确设置索引,如xyz%查询 编辑3:真正的问题是:,mysql,indexing,query-optimization,database-performance,query-performance,Mysql,Indexing,Query Optimization,Database Performance,Query Performance,现在它对联系人使用复合索引,但EXPLAIN只列出了地址的fkey索引,而没有列出我的多列索引或任何其他单列索引 EXPLAIN EXTENDED SELECT c.* FROM Contact_Contact c LEFT OUTER JOIN Address a ON c.id=a.Contact_id WHERE c.deleted<>1 AND c.external<>1 AND ( c.firstName LIKE 'abc%' OR c.las

现在它对联系人使用复合索引,但EXPLAIN只列出了地址的fkey索引,而没有列出我的多列索引或任何其他单列索引

EXPLAIN EXTENDED SELECT c.*
FROM Contact_Contact c 
LEFT OUTER JOIN Address a ON c.id=a.Contact_id 
WHERE c.deleted<>1 
AND c.external<>1 
AND (
  c.firstName LIKE 'abc%' OR
  c.lastName LIKE 'abc%' OR
  c.Company LIKE 'abc%' OR
  c.label LIKE 'abc%' OR
  a.street LIKE 'abc%' OR
  a.city LIKE 'abc%' OR
  a.region LIKE 'abc%') 
GROUP BY c.id 
ORDER BY c.lastName ASC
LIMIT 30
FK_DC6MN93H87CIM4YR8NNIJ3FA是fkey on地址。联系人id

因此,它似乎在联系人上使用多列索引,但在地址上不使用多列索引,该地址定义为:

ADD INDEX `myCompositeAddressIdx` USING BTREE (
  `Contact_id` ASC, `street`(255) ASC, `city`(255) ASC, `region`(255) ASC
);
ADD INDEX `myNEWCompositeAddressIdx` USING BTREE (
  `street`(255) ASC, `city`(255) ASC, `region`(255) ASC
);
知道如何使用myCompositeAddressIdx吗

EDIT4:已修改的查询,速度快30%,子查询上没有索引: 这是我的新查询,需要250毫秒旧的:350毫秒

SELECT c.*
FROM Contact_Contact c
WHERE c.deleted<>1 
AND c.external<>1 
AND (
  c.firstName LIKE 'abc%' OR
  c.lastName LIKE 'abc%' OR
  c.Company LIKE 'abc%' OR
  c.label LIKE 'abc%' OR
  c.id IN (SELECT a.Contact_id FROM Address a WHERE a.street LIKE 'abc%' OR a.city LIKE 'abc%' OR a.region LIKE 'abc%')
  -- ALTERNATIVE:
  -- EXISTS (SELECT 1 FROM Address a WHERE a.Contact_id=c.id AND (a.street LIKE 'abc%' OR a.city LIKE 'abc%' OR a.region LIKE 'abc%'))
)
GROUP BY c.id 
ORDER BY c.lastName ASC
LIMIT 30
将myNEWCompositeAddressIdx定义为:

ADD INDEX `myCompositeAddressIdx` USING BTREE (
  `Contact_id` ASC, `street`(255) ASC, `city`(255) ASC, `region`(255) ASC
);
ADD INDEX `myNEWCompositeAddressIdx` USING BTREE (
  `street`(255) ASC, `city`(255) ASC, `region`(255) ASC
);
原始问题: 我们的MySQL数据库存在一些性能问题,架构如下所示:

TABLE Contact:
id, firstName, lastName, company

TABLE Address:
id, contact_id, street, city

TABLE ContactGroup:
id, name

TABLE Contact_ContactGroup:
contact_id, contact_group_id
还有一些桌子,但总是一样的 所有文本字段最多为255

我们的查询类似于输入abc xyz

在我的开发机器上,联系人表中有130000行,大约需要280ms。我们的服务器需要2秒以上的时间

之前我们有一个独特的而不是小组,但它似乎几乎平等的表现。之前我们也有类似于“%abc%”的内容,但我读到,如果搜索词前面有通配符,MySQL就不能使用索引。查询耗时约310ms

如您所见,查询并没有明显加快。我想我把索引设置错了。我设定的:

Contact Index: primary key
id

Contact Index: BTREE
firstName ASC, lastName ASC, company ASC

Address Index: primary key
id

Address Index: BTREE
street ASC, city ASC

Contact_ContactGroup: compound primary key
contact_id, contact_group_id
在所有数据都已在表中之后,我添加了索引。MySQL是否自动索引旧数据?添加索引不需要超过半秒钟,尽管我不确定它是否真的索引了数据。我找不到强制重新索引表的命令

还是对每一列使用一个单独的列索引,而不是对所有列使用一个庞大的复合索引更好

顺便说一句:我们正在使用MySQL 5.5和InnoDB表


任何帮助都将不胜感激。谢谢:

是否取决于系统,因为此查询在我的服务器上花费了180毫秒, 我碰巧有您的db模式的精确副本,而且在PL/SQL过程开发之前我已经编制了索引

SELECT c.*
FROM Contact c LEFT JOIN Contact_ContactGroup ccg ON ccg.contact_id = c.id
 LEFT JOIN Address a ON a.contact_id = c.id

WHERE
  c.firstName  LIKE 'abc%xyz%' OR
  c.lastName   LIKE 'abc%xyz%' OR
  c.company   LIKE 'abc%xyz%' OR
  a.street   LIKE 'abc%xyz%' OR
  a.city   LIKE 'abc%xyz%' AND
  ccg.contact_group_id IN (1, 2, 3)
GROUP BY
  c.id
ORDER BY
  c.lastName ASC

像“%anything…”一样,根本不能使用索引。考虑使用全文索引。我知道,这就是为什么我们现在只有%。更正了标题,对不起。。。顺便说一句:MySQL的匹配在最后也只支持通配符:anything*有效,*anything不起作用。我肯定你的WHERE子句不是你想要的。您要将所有或表达式放在括号中:c.firstName像“abc%”或c.firstName像“xyz%”或c.lastName像“abc%”或c.company像“abc%”或c.company像“xyz%”或a.street像“abc%”或a.city像“abc%”或a.city像“xyz%”和ccg.contact_group(id在1、2中,3因为和的优先级高于或。我只是写下了那个查询,因为我不想从我们的应用程序中复制和粘贴50行SQL。你是对的,我没有看到括号。我要补充一点,创建索引的时间无关紧要。所有行都被索引。因为您在WHERE子句中引用了ccg,所以MySQL将其视为内部联接。对于内部联接,MySQL更喜欢从具有最高选择性的表开始,并减少行数。这是ccg吗?可能优化这个查询有很多挑战,如果没有更多的信息,例如每个表中的行数、数据的一些概念和解释结果,我们只能猜测。您可以先使用UNION而不是OR。当使用类似“abc%xyz%”而不是类似“abc%”或类似“xyz%”时,这是否真的返回相同的数据。我会尝试一下,但我真的不确定是否有相同的记录。你有多少记录?测试了它,正如预期的那样,它不会返回相同的结果@塞巴斯:我已经在上面的评论中发布了大量的数据。
SELECT c.*
FROM Contact c LEFT JOIN Contact_ContactGroup ccg ON ccg.contact_id = c.id
 LEFT JOIN Address a ON a.contact_id = c.id

WHERE
  c.firstName  LIKE 'abc%xyz%' OR
  c.lastName   LIKE 'abc%xyz%' OR
  c.company   LIKE 'abc%xyz%' OR
  a.street   LIKE 'abc%xyz%' OR
  a.city   LIKE 'abc%xyz%' AND
  ccg.contact_group_id IN (1, 2, 3)
GROUP BY
  c.id
ORDER BY
  c.lastName ASC