sql >> Database >  >> RDS >> Mysql

Hoe kan ik select count(*) versnellen met group by en waar?

Hier zijn verschillende dingen die ik zou proberen, in volgorde van toenemende moeilijkheidsgraad:

(gemakkelijker) - Zorg ervoor dat u de juiste dekkingsindex heeft

CREATE INDEX ix_temp ON relations (relation_title, object_title);

Dit zou perf moeten maximaliseren gezien uw bestaande schema, aangezien (tenzij uw versie van mySQL's optimizer echt dom is!) moet worden gescand) en het dekt de zoekopdracht, zodat u de geclusterde index niet hoeft aan te raken.

(een beetje moeilijker) - zorg ervoor dat uw varchar-velden zo klein mogelijk zijn

Een van de perf-uitdagingen met varchar-indexen op MySQL is dat bij het verwerken van een query de volledige gedeclareerde grootte van het veld in het RAM wordt getrokken. Dus als je een varchar(256) hebt maar slechts 4 tekens gebruikt, betaal je nog steeds het 256-byte RAM-gebruik terwijl de query wordt verwerkt. Au! Dus als u uw varchar-limieten gemakkelijk kunt verkleinen, zou dit uw zoekopdrachten moeten versnellen.

(moeilijker) - Normaliseren

30% van je rijen met een enkele tekenreekswaarde is een duidelijke roep om normalisatie in een andere tabel, zodat je tekenreeksen niet miljoenen keren dupliceert. Overweeg om te normaliseren in drie tabellen en geheeltallige ID's te gebruiken om ze samen te voegen.

In sommige gevallen kun je normaliseren onder de dekens en de normalisatie verbergen met views die overeenkomen met de naam van de huidige tabel... dan hoef je alleen je INSERT/UPDATE/DELETE-query's bewust te maken van de normalisatie, maar je kunt je SELECT's met rust laten .

(moeilijkste) - Hash je stringkolommen en indexeer de hashes

Als normaliseren betekent dat u te veel code moet wijzigen, maar u uw schema een klein beetje kunt wijzigen, kunt u overwegen 128-bits hashes te maken voor uw tekenreekskolommen (met behulp van de MD5-functie ). In dit geval (in tegenstelling tot normalisatie) hoeft u niet al uw vragen te wijzigen, alleen de INSERT's en enkele van de SELECT's. Hoe dan ook, u wilt uw stringvelden hashen en vervolgens een index maken op de hashes, b.v.

CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Houd er rekening mee dat u met de SELECT moet spelen om ervoor te zorgen dat u de berekening uitvoert via de hash-index en niet de geclusterde index binnenhaalt (vereist om de werkelijke tekstwaarde van object_title op te lossen om aan de query te voldoen).

Als relation_title een kleine varchar-grootte heeft, maar de objecttitel een lange grootte, dan kunt u mogelijk alleen object_title hashen en de index maken op (relation_title, object_title_hash) .

Merk op dat deze oplossing alleen helpt als een of beide velden erg lang zijn in verhouding tot de grootte van de hashes.

Merk ook op dat hashing interessante effecten op hoofdlettergevoeligheid/sortering heeft, aangezien de hash van een tekenreeks in kleine letters niet hetzelfde is als een hash van een hoofdletter. Je moet er dus voor zorgen dat je canonicalization toepast op de strings voordat je ze hasht - met andere woorden, hash alleen kleine letters als je in een hoofdletterongevoelige DB zit. Mogelijk wilt u ook spaties vanaf het begin of einde inkorten, afhankelijk van hoe uw DB voor-/achterafgaande spaties verwerkt.



  1. Hoe de LIKE-operator werkt in SQLite

  2. Een Oracle-database migreren van AWS EC2 naar AWS RDS, deel 2

  3. Waar worden de JPA @Table annotatiecatalogus en schemavariabelen voor gebruikt?

  4. EF Core `update-database` op MySql mislukt met `__EFMigrationsHistory' bestaat niet`