Ich möchte alle Benutzer und den Status des Newsletter-Abonnements auflisten. Da jemand muss kein Benutzer sein, wenn Sie den Newsletter abonniert haben, mache ich so etwas wie:MySql: Unterabfrage mit index_merge optimieren
SELECT user.id, user.email,
(SELECT newsletter.status FROM newsletter
WHERE newsletter.email=user.email OR newsletter.user = user.id) AS status
FROM user
WHERE...
Indizes sind user.id, user.email, newsletter.email, newsletter.user.
Das OR macht die Abfrage unglaublich langsam. Ich habe hier Union as sub query MySQL gefunden, dass Sie eine "Indexzusammenführung" durchführen können, die die Abfrage beschleunigen wird. Aber ich bin nicht sicher, wie MySQL in meinem Fall eine Indexzusammenführung erzwingt. Irgendwelche Ideen?
Hinzugefügt: 2. Zeile von EXPLAIN verwendet keinen Schlüssel.
DROP TABLE if exists user;
DROP TABLE if exists newsletter;
create table user (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`email` varchar(255) DEFAULT NULL, INDEX email(email)
) ENGINE=InnoDB;
create table newsletter (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`status` enum('subscribed','unsubscribed') DEFAULT NULL,
`email` varchar(255) DEFAULT NULL, INDEX email(email),
`user` int(10) unsigned DEFAULT NULL, INDEX user(user)
) ENGINE=InnoDB;
EXPLAIN SELECT user.id, user.email,
(SELECT newsletter.status FROM newsletter
WHERE newsletter.email=user.email OR newsletter.user = user.id) AS status
FROM user;
+----+--------------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
| 1 | PRIMARY | user | NULL | index | NULL | email | 768 | NULL | 1 | 100.00 | Using index |
| 2 | DEPENDENT SUBQUERY | newsletter | NULL | ALL | email,user | NULL | NULL | NULL | 1 | 100.00 | Range checked for each record (index map: 0x6) |
+----+--------------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
EXPLAIN SELECT user.id, user.email, newsletter.status
FROM user
LEFT JOIN newsletter ON (newsletter.email=user.email OR newsletter.user = user.id);
+----+-------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
| 1 | SIMPLE | user | NULL | index | NULL | email | 768 | NULL | 1 | 100.00 | Using index |
| 1 | SIMPLE | newsletter | NULL | ALL | email,user | NULL | NULL | NULL | 1 | 100.00 | Range checked for each record (index map: 0x6) |
+----+-------------+------------+------------+-------+---------------+-------+---------+------+------+----------+------------------------------------------------+
Haben Sie versucht, beitreten? –
Ja, dasselbe Problem: LINKER JOIN-Newsletter EIN (newsletter.user = users.id ODER newsletter.email = users.email) => langsam. – Werner
Sie sollten Ihre Tabellendefinitionen zusammen mit einem EXPLAIN-Plan veröffentlichen. –