Jeg har lavet nogle forbedringer i JOIN
version; se nedenfor.
Jeg stemmer for JOIN-tilgangen for hurtighed. Sådan fandt jeg det ud:
HAVING, version 1
mysql> FLUSH STATUS;mysql> SELECT by -> FROM us_vch200 -> WHERE state IN ('IL', 'MO', 'PA') -> GRUPPER EFTER by -> HAVING count (DISTINCT state)>=3;+-------------+| by |+-------------+| Springfield || Washington |+-------------+mysql> VIS SESSIONSSTATUS SOM 'Handler%';+---------------------------- -------+-------+| Variabelnavn | Værdi |+-----------------------------+-------+| Handler_ekstern_lås | 2 || Handler_read_first | 1 || Handler_read_key | 2 || Handler_read_last | 1 || Handler_read_next | 4175 | -- fuld indeks scanning(etc)+----+-------------------------+--- ----------------------+-------------+--------+----- --+------+----------------------------------------- ----------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+------------+-------+-------- ---------------+------------+--------+------+---- --+----------------------------------------------- ---+| 1 | ENKELT | us_vch200 | rækkevidde | stat_by, bystat | bystat | 769 | NULL | 4176 | Brug af hvor; Brug af indeks til gruppe-efter (scanning) |+----+-------+-----+------+ -----------------------+------------+--------+--- ---+------+--------------------------------------------- -----------+
'Extra' påpeger, at den besluttede at tackle GROUP BY
og brug INDEX(by, stat)
selvom INDEX(stat, by)
kan give mening.
HAVING, version 2
Får det til at skifte til INDEX(stat, by)
giver:
mysql> FLUSH STATUS;mysql> SELECT by -> FROM us_vch200 IGNORE INDEX(city_state) -> WHERE state IN ('IL', 'MO', 'PA') -> GRUPPER EFTER by -> HAR count(DISTINCT state)>=3;+--------+| by |+-------------+| Springfield || Washington |+-------------+mysql> VIS SESSIONSSTATUS SOM 'Handler%';+---------------------------- -------+-------+| Variabelnavn | Værdi |+-----------------------------+-------+| Handler_commit | 1 || Handler_ekstern_lås | 2 || Handler_read_key | 401 || Handler_read_next | 398 || Handler_read_rnd | 398 |(osv)+----+---------------+-------------+----- ------------------+------------+---------+------+- -----+--------------------------------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+-------------+------------+-------+-------- ---------------+------------+--------+------+---- --+-------------------------------------------------+| 1 | ENKELT | us_vch200 | rækkevidde | stat_by, bystat | stat_by | 2 | NULL | 397 | Brug af hvor; Brug af indeks; Brug af filersortering |+----+--------------+-------+-------+------- --------------+------------+---------+------+--- ---+--------------------------------------------------+
DELTAG
mysql> VÆLG x.city -> FRA us_vch200 x -> JOIN us_vch200 y ON y.city=x.city OG y.state ='MO' -> JOIN us_vch200 z ON z.city=x. by OG z.state ='PA' -> HVOR x.state ='IL';+-------+| by |+-------------+| Springfield || Washington |+-------------+2 rækker i sæt (0,00 sek.)mysql> VIS SESSIONSSTATUS SOM 'Handler%';+-------- ---------------+-------+| Variabelnavn | Værdi |+-----------------------------+-------+| Handler_commit | 1 || Handler_ekstern_lås | 6 || Handler_read_key | 86 || Handler_read_next | 87 |(osv) +----+--------------+-------+------+-------- --------------+-------------+---------+------- -------+------+--------------------------+| id | vælg_type | bord | type | mulige_nøgler | nøgle | key_len | ref | rækker | Ekstra |+----+--------------+-------+------+------- ----------+------------+---------+---------------- ----+------+---------------------------------+| 1 | ENKELT | y | ref | stat_by, bystat | stat_by | 2 | konst | 81 | Brug af hvor; Brug af indeks || 1 | ENKELT | z | ref | stat_by, bystat | stat_by | 769 | const,world.y.city | 1 | Brug af hvor; Brug af indeks || 1 | ENKELT | x | ref | stat_by, bystat | stat_by | 769 | const,world.y.city | 1 | Brug af hvor; Brug af indeks |+----+-------------+-------+------+------------ ----------------------------------------- -----+------+---------------------------------+
Kun INDEX(stat, by)
er nødvendig. Handler-tallene er de mindste for denne formulering, så jeg udleder, at det er det hurtigste.
Læg mærke til, hvordan optimeringsværktøjet besluttede sig for, hvilken tabel han skulle starte med, sandsynligvis på grund af
+-------+----------+| stat | COUNT(*) |+-------+----------+| IL | 221 || MO | 81 | -- mindste| PA | 96 |+-------+----------+
Konklusioner
JOIN
(uden den unødvendige t
tabel) er nok den hurtigste. Plus dette sammensatte indeks er nødvendigt:INDEX(stat, by)
.
Sådan oversætter du tilbage til din use case:
by --> documentidstate --> termid
Advarsel:YMMV, fordi fordelingen af værdier for documentid og termid kunne være helt anderledes end den testcase, jeg brugte.