Ich habe keine Kontrolle über Dinge wie tmp_table_size
und max_heap_table_size
, und wenn unsere Tabellen wachsen, wächst die Zeit, die Abfragen benötigen, die temporäre Tabellen erfordern, geometrisch.
Ich frage mich, ob es eine Möglichkeit gibt, MySQL daran zu hindern, temporäre Tabellen für diese Abfragen zu verwenden. Was wäre der beste Ansatz in dieser Situation:
Hier ist ein Beispiel für den größten Täter:
SELECT `skills`.`id`
FROM (`jobs_skills`)
JOIN `jobs` ON (`jobs`.`id` = `jobs_skills`.`job_id`)
JOIN `skills` ON (`skills`.`id` = `jobs_skills`.`skill_id`)
WHERE `jobs`.`job_visibility_id` = 1
AND `jobs`.`active` = 1
AND `skills`.`valid` = 1
AND `jobs_skills`.`skill_id` IN (96,101,103,108,121,2610,99,119,2607,102,104,112,113,122,1032,1488,2608,109,126,1438,2310,2318,2622,118,1046,1387,2609,100,116,123,2611,2612,2616,2618,114,127,1562,1587,1608,2276,2615,125,1070,1071,1161,1658,2613,2614,2617,105,110,111,120,1394,1435)
GROUP BY `jobs_skills`.`job_id`
Dies copying to temp table
dauerte 107 Sekunden, 99% der gesamten Abfragezeit.
Trotz der Befürchtungen des Dr.-Syndroms biete ich an. . .
MEHR DETAILS
Hier ist die EXPLAIN
Anweisung für die Abfrage:
+----+-------------+-------------+--------+----------------------+--------------+---------+----------------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+----------------------+--------------+---------+----------------------------------+--------+----------------------------------------------+
| 1 | SIMPLE | jobs | ref | PRIMARY,active_index | active_index | 1 | const | 468958 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | jobs_skills | ref | PRIMARY | PRIMARY | 4 | 557574_prod.jobs.id | 1 | Using where; Using index |
| 1 | SIMPLE | skills | eq_ref | PRIMARY | PRIMARY | 4 | 557574_prod.jobs_skills.skill_id | 1 | Using where |
+----+-------------+-------------+--------+----------------------+--------------+---------+----------------------------------+--------+----------------------------------------------+
und hier sind die CREATE TABLE
Aussagen für die relevanten Tabellen:
| jobs | CREATE TABLE `jobs` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) unsigned NOT NULL,
`title` varchar(40) NOT NULL,
`description` text NOT NULL,
`address_id` int(10) unsigned NOT NULL,
`proximity` smallint(3) unsigned NOT NULL default '15',
`job_payrate_id` tinyint(1) unsigned NOT NULL default '1',
`payrate` int(10) unsigned NOT NULL,
`start_date` int(10) unsigned NOT NULL,
`job_start_id` tinyint(1) unsigned NOT NULL default '1',
`duration` tinyint(1) unsigned NOT NULL COMMENT 'Full-time, Part-time, Flexible',
`posting_date` int(10) unsigned NOT NULL,
`revision_date` int(10) unsigned NOT NULL,
`expiration` int(10) unsigned NOT NULL,
`active` tinyint(1) unsigned NOT NULL default '1',
`team_size` tinyint(2) unsigned NOT NULL default '1',
`job_type_id` tinyint(1) unsigned NOT NULL default '1',
`job_shift_id` tinyint(1) unsigned NOT NULL default '1',
`job_visibility_id` tinyint(1) unsigned NOT NULL default '1',
`position_count` smallint(5) unsigned NOT NULL default '1',
`impressions` int(10) unsigned NOT NULL default '0',
`clicks` int(10) unsigned NOT NULL default '0',
`employer_email` varchar(100) NOT NULL default '',
`job_source_id` smallint(6) unsigned NOT NULL default '0',
`job_password` varchar(50) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `active_index` (`active`),
KEY `user_id_index` (`user_id`),
KEY `address_id_index` (`address_id`),
KEY `posting_date_index` USING BTREE (`posting_date`)
) ENGINE=InnoDB AUTO_INCREMENT=875013 DEFAULT CHARSET=utf8
- -
| jobs_skills | CREATE TABLE `jobs_skills` (
`job_id` int(10) unsigned NOT NULL,
`skill_id` int(10) unsigned NOT NULL,
`required` tinyint(1) unsigned NOT NULL,
PRIMARY KEY (`job_id`,`skill_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
- -
| skills | CREATE TABLE `skills` (
`id` int(10) unsigned NOT NULL auto_increment,
`parent_id` int(10) unsigned NOT NULL,
`name` varchar(35) NOT NULL default '',
`description` varchar(250) NOT NULL,
`valid` tinyint(1) unsigned NOT NULL default '0',
`is_category` tinyint(1) unsigned NOT NULL default '0',
`last_edited` int(10) unsigned NOT NULL default '0',
`impressions` int(10) unsigned NOT NULL default '0',
`clicks` int(10) unsigned NOT NULL default '0',
`jobs` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `parent` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2657 DEFAULT CHARSET=utf8 |
Wie ich bereits sagte, ist dies nicht die einzige Abfrage mit diesem Problem. Daher wäre jeder allgemeine Rat am hilfreichsten, obwohl ich keinen für diese Abfrage spezifischen Rat ablehnen werde.
quelle
Antworten:
Ihre ursprüngliche Unterabfrage:
Sie müssen die Abfrage so rafaktorisieren, dass Sie die zu erstellenden temporären Tabellen und ihre Größe steuern und mikromanagen. Basierend auf den Klauseln JOIN, WHERE und GROUP BY müssen Sie die folgenden Änderungen implementieren:
Jobs müssen auf job_visibility_id, active, id indiziert werden
Benötigte Unterabfrage
Fähigkeiten müssen auf gültige ID indiziert werden
Benötigte Unterabfrage
jobs_skills muss auf Skill_id, Job_id indiziert werden
Benötigte Unterabfrage
SQL zum Erstellen der erforderlichen Indizes
Kombinieren Sie nun die Unterabfragen zu VOLTRON
Versuche es !!!
Übrigens, wenn die Syntax falsch ist, werde ich versuchen, sie anzupassen !!!
quelle