sql >> Databasteknik >  >> RDS >> Mysql

Hur snabbar man upp antalet valda(*) med grupp efter och var?

Här är flera saker jag skulle försöka, i ökande svårighetsgrad:

(enklare) - Se till att du har rätt täckande index

CREATE INDEX ix_temp ON relations (relation_title, object_title);

Detta bör maximera prestanda givet ditt befintliga schema, eftersom (om inte din version av mySQL:s optimizer är riktigt dum!) kommer det att minimera mängden I/O som behövs för att tillfredsställa din fråga (till skillnad från om indexet är i omvänd ordning där hela indexet måste skannas) och det kommer att täcka frågan så att du inte behöver röra det klustrade indexet.

(lite svårare) – se till att dina varcharfält är så små som möjligt

En av de perfekta utmaningarna med varchar-index på MySQL är att, när en fråga bearbetas, kommer den fulla deklarerade storleken på fältet att dras in i RAM. Så om du har en varchar(256) men bara använder 4 tecken, betalar du fortfarande 256-byte RAM-användningen medan frågan bearbetas. aj! Så om du enkelt kan krympa dina varchar-gränser borde detta påskynda dina frågor.

(hårdare) - Normalisera

30 % av dina rader med ett enda strängvärde är ett tydligt rop på normalisering till en annan tabell så att du inte duplicerar strängar miljoner gånger. Överväg att normalisera till tre tabeller och använda heltals-ID:n för att sammanfoga dem.

I vissa fall kan du normalisera under täcket och dölja normaliseringen med vyer som matchar namnet på den aktuella tabellen... då behöver du bara göra dina INSERT/UPDATE/DELETE-frågor medvetna om normaliseringen men kan lämna dina SELECTs ifred .

(svårast) – Hasha dina strängkolumner och indexera hasharna

Om normalisering innebär att du ändrar för mycket kod, men du kan ändra ditt schema lite, kanske du vill överväga att skapa 128-bitars hash för dina strängkolumner (med MD5-funktion ). I det här fallet (till skillnad från normalisering) behöver du inte ändra alla dina frågor, bara INSERT och några av SELECT. Hur som helst, du vill hasha dina strängfält och sedan skapa ett index på hasharna, t.ex.

CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Observera att du måste leka med SELECT för att se till att du gör beräkningen via hashindexet och inte drar in det klustrade indexet (krävs för att lösa det faktiska textvärdet för object_title för att tillfredsställa frågan).

Dessutom, om relation_title har en liten varchar-storlek men objekttitel har en lång storlek, kan du potentiellt hasha endast object_title och skapa indexet på (relation_title, object_title_hash) .

Observera att den här lösningen bara hjälper om ett eller båda dessa fält är mycket långa i förhållande till storleken på hasharna.

Observera också att det finns intressanta skiftlägeskänslighet/sorteringseffekter från hash, eftersom hash för en gemen sträng inte är detsamma som en hash för en versal. Så du måste se till att du tillämpar kanonisering på strängarna innan du hashar dem - med andra ord, hash bara gemener om du är i en skiftlägesokänslig DB. Du kanske också vill trimma mellanslag från början eller slutet, beroende på hur din DB hanterar inledande/efterföljande mellanslag.



  1. MySQL -- Uppdatera om det finns annat infoga med två nycklar

  2. Saker du bör veta innan du lär dig Oracle

  3. Neo4j installation

  4. Vad motsvarar varchar(max) i Oracle?