Weißt du, du erstellst (deklarierst) hier ein global Array.
Das wird im Heap reserviert.
[MAX_PLAYERS][33];
Mal angenommen MAX_PLAYERS sind 500.
Dann würdest du hier 500*33*4 Bytes = 66000 Bytes = 64.45KiloBytes
in der .amx reservieren nur um ein paar TextDraw ids zu speichern.
Also ich fände das nicht gerade sehr schön xD
Besonders wenn du noch mehr TextDraws hast..reservierst du da hunderte KiloBytes an speicher...für nix xD
Ein trick wäre...die Nutzung von "Pointers".
1. Möglichkeit:
new PlayerText:LoginTextDraw[MAX_PLAYERS][2]; //Sind 4000 Bytes..aber besser als 66000 xD
new PlayerText:x = LoginTextDraw[playerid][0] = CreatePlayerTextDraw(...); //Hier beim ersten
TextDrawPlayerTextDrawSetXX(x, true); //Nutzen dann hier mit x
x = CreatePlayerTextDraw(...); //Hier einfach auf x zuweisen und die ID nutzen (bei allen)
PlayerTextDrawSetXX(x, true); //Nutzen dann hier mit x
//und ganz zum schluss:
LoginTextDraw[playerid][1] = x; //Jetzt weißt du..wo es anfängt und aufhört
//Loop würde z.B. so aussehen:
new len = _:LoginTextDraw[playerid][1]+1;
for(new textid=_:LoginTextDraw[playerid][0]; textid<len; textid++)
{
PlayerTextDrawHide(playerid, PlayerText:textid);
}
Alles anzeigen
2. Möglichkeit:
Nutzung von 2 PVars.
Sieht genau gleich aus..nur mit Set & Get nutzen.
Dann kann man auch, z.B. wenn es nur um den Login geht...DeletePVar & PlayerTextDrawDestroy machen und verbrauchst nun so 0 Speicher 
Fazit:
Würdest du Möglichkeit 1 nutzen, dann würdest du bei 100000 Iterationen...dir ca 2ms sparen. Allerdings würdest du immernoch jede Menge Speicher reservieren. Allerdings kannst du nun abwegen ob dir 2ms CPU wichtiger sind...oder ein Speicherverbrauch von 0 Bytes